Heim > Web-Frontend > js-Tutorial > Tutorial zum Erstellen des vue2 vue-router2 webpack3-Projekts

Tutorial zum Erstellen des vue2 vue-router2 webpack3-Projekts

小云云
Freigeben: 2018-01-16 09:13:20
Original
1263 Leute haben es durchsucht

In diesem Artikel wird hauptsächlich die detaillierte Erklärung zum Erstellen des vue2 vue-router2 webpack3-Projekts von Grund auf vorgestellt. Der Herausgeber findet es ziemlich gut, daher werde ich es jetzt mit Ihnen teilen und als Referenz geben. Folgen wir dem Herausgeber und werfen wir einen Blick darauf. Ich hoffe, es hilft allen.

Aus der Sicht eines Anfängers werden wir den Inhalt jedes Schritts im Detail vorstellen. Wir werden nicht ausführlich auf die mit den Schritten verbundenen Prinzipien eingehen, sondern hauptsächlich die Funktionsweise vorstellen.

Initialisieren Sie das Projekt

Erstellen Sie ein neues Projektverzeichnis vue2practice, führen Sie npm init -y im Verzeichnis aus, um eine package.json zu erstellen, und fügen Sie zuerst die folgenden erforderlichen Module zu package.json hinzu:

{

 "name": "vue2-vue-router2-webpack3",

 "version": "1.0.0",

 "devDependencies": {

  "vue": "^2.4.2",

  "vue-loader": "^13.0.2",

  "vue-router": "^2.7.0",

  "vue-template-compiler": "^2.4.2",

  "webpack": "^3.4.1",

  "webpack-dev-server": "^2.6.1"

 }

}
Nach dem Login kopieren

Unter anderem installiert der Vue-Template-Compiler die PeerDependencies von Vue-Loader nicht automatisch. Der Vue-Template-Compiler ist jedoch notwendig in Abhängigkeiten? Jemand hat diese Frage auf Github gestellt. Lassen Sie mich die Antwort des Autors grob übersetzen (nur als Referenz): Der Grund dafür ist, dass es keine zuverlässige Möglichkeit gibt, die Beziehung verschachtelter Abhängigkeiten zu beheben. Erstens sind die Versionsnummern von vue-template-compiler und vue konsistent (derzeit synchron aktualisiert). Die Angabe von vue-template-compiler als Abhängigkeit von vue-loader garantiert nicht, dass die Versionsnummern von vue-template-compiler und vue sind gleich, sodass Benutzer die Version angeben können, um dies sicherzustellen. Sehen Sie sich die Antwort des Autors an (auf Englisch). Wenn die beiden Versionen inkonsistent sind, wird beim Ausführen die in der folgenden Abbildung gezeigte Fehlermeldung angezeigt.

Die neue Verzeichnisstruktur sieht wie folgt aus: Lassen Sie die neu hinzugefügten Verzeichnisse und Dateien zunächst leer. In den folgenden Schritten wird erläutert, welche Inhalte hinzugefügt werden sollen.

vue2pratice

  |-- package.json

  |-- index.html     // 启动页面

  |-- webpack.config.js // webpack配置文件

  |-- src

    |-- views    // vue页面组件目录

    |-- main.js   // 入口文件

    |-- router.js  // vue-router配置

    |-- app.vue   // 工程首页组件
Nach dem Login kopieren

Webpack konfigurieren

Webpack liest standardmäßig webpack.config.js. Der Dateiname kann nicht zufällig geändert werden und der Eintrag muss konfiguriert werden.

module.exports = {

  entry: './src/main.js',

  output: {

    path: __dirname + '/dist',

    publicPath: '/static/',

    filename: 'build.js'

  }

}
Nach dem Login kopieren

Webpack 2+ erfordert, dass „output.path“ ein absoluter Pfad ist.

Um den Webpack-Dev-Server zu konfigurieren, fügen Sie einfach den folgenden Startbefehl zu package.json hinzu.

"scripts": {

 "dev": "webpack-dev-server --hot --open"

}
Nach dem Login kopieren

webpack-dev-server 2 ist standardmäßig im Inline-Modus, der Hot-Modul-Austausch muss noch von Ihnen selbst eingerichtet werden.

Konfiguration überprüfen

Testcode in index.html hinzufügen und die gepackte JS-Datei einführen.

<body>

  Hello, Webpack 3.

  <br>

  <script src="/static/build.js"></script>

</body>
Nach dem Login kopieren

Testcode in main.js hinzufügen.

// main.js

document.write('来自main.js的问候!')
Nach dem Login kopieren

Führen Sie die folgenden Befehle aus, um das Modul zu installieren und den Server zu starten.

// 安装依赖

npm install

 

// 运行

npm run dev
Nach dem Login kopieren

Nach dem Start öffnet der Browser automatisch http://localhost:8080. Wenn in der Konsole kein Fehler gemeldet wird, zeigt die Seite den Inhalt von main.js und index.html korrekt an. Nach dem Ändern von main.js zeigt der Browser den Effekt an, ohne ihn zu aktualisieren. Dies bedeutet, dass kein Problem mit der Konfiguration vorliegt.

Vue

Neue Seite

Erstellen Sie eine neue index.vue im Ansichtenverzeichnis.

<template>

  <p>

    这是{{page}}页面

  </p>

</template>

<script>

export default {

  data: function () {

    return {

      page: 'index'

    }

  }

}

</script>
Nach dem Login kopieren

Webpack 1 erfordert einen speziellen Loader zum Konvertieren des ES 2015-Imports/Exports, Webpack 2 und höher können sofort verwendet werden. Die neue Syntax von ES6 erfordert jedoch weiterhin eine Konvertierung durch den Loader. Verwenden Sie die neue Syntax nicht ohne Konfiguration. Nach der Verwendung werden keine Fehler gemeldet (z. B. let, const usw.), da Ihr Browser bereits die ES6-Syntax unterstützt (neue Browserversionen unterstützen sie bereits).

Routing konfigurieren

Extrahieren Sie den von der Vue-Router-Instanziierung übergebenen Parameter „New VueRouter“ (Parameter) in router.js, um eine Routing-Konfigurationsdatei zu erstellen.

import index from './views/index.vue'

export default {

  routes: [

    {

      path: '/index',

      component: index

    }

  ]

}
Nach dem Login kopieren

Ab vue-loader@13.0.0 können Sie require nicht mehr zum Einführen von .vue-Dateien verwenden, da .vue-Dateien schließlich in ES6-Module kompiliert werden.

Homepage

Die Homepage stellt den JS der Ausgabekonfiguration vor und fügt das Montageziel der Vue-Instanz hinzu.

<body>

<p id="app"></p>

<script src="/static/build.js"></script>

</body>
Nach dem Login kopieren

Der Eintrag JS schließt die Routing-Konfiguration ab und initialisiert die Vue-Instanz.

import Vue from 'vue';

import VueRouter from 'vue-router';

import App from './app.vue';

import routerConfig from './router';

Vue.use(VueRouter);

var router = new VueRouter(routerConfig)

new Vue({

  el: '#app',

  router: router,

  render: h => h(App)

});
Nach dem Login kopieren

Wenn Sie require('vue') ab Vue 2.2.0 verwenden, wird ein Fehler gemeldet. Sie sollten das ES6-Modul (Import) verwenden. Weitere Informationen finden Sie im Vue-Update Anweisungen https://github.com/vuejs/ vue/releases, der Screenshot sieht wie folgt aus:

Routing-Links und Routing-Ansichtskomponenten zur Homepage-Komponenten-App hinzufügen. vue.

<template>

  <p>

    <p>

      <router-link to="/index">Home</router-link>

    </p>

    <p>

      <router-view></router-view>

    </p>

  </p>

</template>
Nach dem Login kopieren

Loader konfigurieren

Konfigurieren Sie den Loader entsprechend der Vue-Datei.

module: {

  rules: [

    {

      test: /\.vue$/,

      use: ["vue-loader"]

    }

  ]

}
Nach dem Login kopieren

Webpack2 muss den Loader unter module.rules konfigurieren. „-loader“ darf nicht weggelassen werden, der Loader-Name muss vollständig geschrieben werden. Sie können Rule.use oder Rule.loader verwenden, um den Loader zu konfigurieren (Rule.loader ist die Abkürzung von Rule.use: [ {loader } ] Es wird empfohlen, use zu verwenden).

Mit den obigen Schritten ist die Konfiguration abgeschlossen, die zum Hinzufügen einer neuen Seite und zum Zugriff auf die Seite erforderlich ist. Jetzt testen wir, ob auf /index normal zugegriffen werden kann. Führen Sie npm run dev aus und der Browser zeigt die in der Abbildung gezeigte Schnittstelle an.

CSS unterstützen

Sie können es nach der Installation des CSS-Loaders in Vue-Dateien verwenden

npm i css-loader -D
Nach dem Login kopieren

Möchten Sie den Import unterstützen / erfordern Beim Einführen von CSS-Dateien müssen Sie die entsprechende Regel konfigurieren.

{

  test: /\.css$/,

  use: ["vue-style-loader", "css-loader"]

}
Nach dem Login kopieren
<script>

import "../style/style.css"

</script>
Nach dem Login kopieren

Unterstützung der CSS-Vorverarbeitungssprache

Nehmen Sie den Stift als Beispiel, installieren Sie den Stift und den Stiftlader.

npm install stylus stylus-loader -D
Nach dem Login kopieren

Fügen Sie die Loader-Konfiguration hinzu, die der .styl-Datei entspricht.

{

  test: /\.styl$/,

  use: ["vue-style-loader", "css-loader", "stylus-loader"]

}
Nach dem Login kopieren

Anwendungsbeispiel:

<style lang="stylus">

  .stylus

    .red

      color red

</style>

<script>

  import "../css/stylus-example.styl"

</script>
Nach dem Login kopieren

Lösung für die langsame Installation von Node-Sass

Taobao-Spiegel verwenden:

npm set disturl https://npm.taobao.org/dist
Nach dem Login kopieren

Sie können das Node-Sass-Bild auch separat festlegen:

npm set sass_binary_site http://cdn.npm.taobao.org/dist/node-sass
Nach dem Login kopieren

Unterstützt Bild- und Symbolschriftarten

安装图片及图标字体依赖的loader。

npm install url-loader file-loader -D
Nach dem Login kopieren

增加图片及图标字体的loader配置。

{

  test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,

  use: [{

    loader: "url-loader",

    options: {

      limit: 10000,

      name: 'images/[name].[hash:7].[ext]'  // 将图片都放入images文件夹下,[hash:7]防缓存

    }

  }]

},

{

  test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,

  use: [{

    loader: "url-loader",

    options: {

      limit: 10000,

      name: 'fonts/[name].[hash:7].[ext]'  // 将字体放入fonts文件夹下

    }

  }]

}
Nach dem Login kopieren

构建

添加打包命令如下:

"build":"webpack --progress --colors"
Nach dem Login kopieren

执行npm run build开始构建,完成后,可以看到工程目录下多了dist目录以及 dist/build.js。 

使用 Webpack 插件

压缩JS

在之前的文章提到过,打开未压缩版的build.js,你会发现ES6的语法没有被转化为ES5,因此需要安装babel 套件来完成语法的转化,否则压缩的时候就会报错。之前广泛使用的转码规则为 babel-preset-es2015,但 Babel 的官网上在9月宣布 ES2015 / ES2016/ ES2017 等等 ES20xx 时代的 presets 通通被废弃(deprecated),取而代之的是 babel-preset-env,并且承诺它将成为“未来不会过时的(future-proof)”解决方案。

npm i babel-loader babel-core babel-preset-env -D
Nach dem Login kopieren

增加babel的配置文件.babelrc。

{

  "presets": [

    ["env", { "modules": false }]

  ],

  "comments": false

}
Nach dem Login kopieren

将 modules 设置为 false,即交由 Webpack 来处理模块化,通过其 TreeShaking 特性将有效减少打包出来的 JS 文件大小,可以自行对比下前后打包出来的文件的大小,效果还是不错的。

comments 即是否保留注释。

接着配置 JS 文件的 loader。

{

  test: /\.js$/,

  use: "babel-loader",

  include: [path.resolve(__dirname, 'src')]

}
Nach dem Login kopieren

注意:Webpack2建议尽量避免exclude,更倾向于使用include。

压缩 JS 采用webpack.optimize.UglifyJsPlugin,配置如下:

new webpack.optimize.UglifyJsPlugin()
Nach dem Login kopieren

官网称warnings默认为false,你可能会遇到即使没有配置warnings: true,控制台仍显示警告,看下面这段源码就知道了。查看源码

只有当options.compress !== false时 warnings 才会被设置默认值 false,所以一旦配置了 compress 其它选项,那就需同时配置warnings: false。

warnings作用是当插件在压缩过程中移除的无效代码或定义是显示警告信息(display warnings when dropping unreachable code or unused declarations etc.)。

提取CSS

使用extract-text-webpack-plugin插件提取CSS。更改 css 及 less 的 loader 配置如下。

// 安装插件

npm i extract-text-webpack-plugin -D
Nach dem Login kopieren
// var ExtractTextPlugin = require("extract-text-webpack-plugin")

{

  test: /\.css$/,

  use: ExtractTextPlugin.extract({

    use: "css-loader"

  })

},

{

  test: /\.styl$/,

  use: ExtractTextPlugin.extract({

    use: ["css-loader", "stylus-loader"]

  })

}
Nach dem Login kopieren

上述配置并不能提取 vue 文件中的 style,需要设置 vue-loader 参数才可以。

{

  test: /\.vue$/,

  use: {

    loader: "vue-loader",

    options: {

      loaders: {

        css: ExtractTextPlugin.extract({

          use: 'css-loader'

        }),

        stylus: ExtractTextPlugin.extract({

          use: ["css-loader", "stylus-loader"]

        })

      }

    }

  }

}
Nach dem Login kopieren

初始化插件,filename 可以指定 CSS 文件的目录。

new ExtractTextPlugin({

  filename: "css/style.css"

})
Nach dem Login kopieren

PostCSS

安装 postcss-loader 及 postcss 插件。

npm i postcss-loader cssnano -D
Nach dem Login kopieren

配置 loader 如下:

// css-loader配置改为

use: ['css-loader', "postcss-loader"]

// stylus-loader配置改为

use: ["css-loader", "postcss-loader", "stylus-loader"]
Nach dem Login kopieren

postcss-loader 要放在 css-loader 和 style-loader 之后,CSS 预处理语言 loader 之前(stylus-loader)。

新增 postcss.config.js 来配置postcss插件,这样就不用给每个 postcss-loader 去配置。更多 postcss-loader 的配置方式请参考 postcss-load-config。

module.exports = {

  plugins: [

    require('cssnano')

  ]

}
Nach dem Login kopieren

cssnano 使用了一系列 postcss 插件,包含了常用的 autoprefixer 等,如何传入 autoprefixer 的配置?

require('cssnano')({

  autoprefixer: {

    add: true,

    browsers: ['> 5%']

  }

})
Nach dem Login kopieren

其中有一个插件 postcss-zindex 使用中发现有些问题。如果想禁用这个插件的话,配置如下:

require('cssnano')({

  zindex: {

    disable:true

  }

})
Nach dem Login kopieren

附:postcss插件分类搜索网站:http://postcss.parts/

生成首页

安装 html-webpack-plugin 插件。

npm i html-webpack-plugin -D
Nach dem Login kopieren

初始化插件。

// var HtmlWebpackPlugin = require('html-webpack-plugin');

new HtmlWebpackPlugin({

  filename: 'index.html',

  template: 'index.tpl.html'

})
Nach dem Login kopieren

其它插件

Webpack3 新增的作用域提升。

new webpack.optimize.ModuleConcatenationPlugin()
Nach dem Login kopieren

指定生产环境,以便在压缩时可以让 UglifyJS 自动删除代码块内的警告语句。

new webpack.DefinePlugin({

  'process.env.NODE_ENV': JSON.stringify('production')

})
Nach dem Login kopieren

因为这个插件直接做的文本替换,给定的值必须包含字符串本身内的实际引号。通常,有两种方式来达到这个效果,使用 '"production"', 或者使用 JSON.stringify('production')。

你完全可以在自己的代码中使用process.env.NODE_ENV来区分开发和生产,从而针对不同的环境做一些事情。不用担心这部分代码会被保留,最终会被 UglifyJS 删除。例如:

if (process.env.NODE_ENV != "production") {

  // 开发环境

}

// webpack.DefinePlugin插件替换后,上述代码会变成

if ("production" != "production") {

  // 开发环境

}

// 输出

if (false) {

  // 开发环境

}

// UglifyJS 会删除这段无效代码
Nach dem Login kopieren

使用上述插件后再次构建,会发现生成的JS相比原来的体积小了不少。

friendly-errors-webpack-plugin 是一个更友好显示 webpack 错误信息的插件。插件 github 地址:https://github.com/geowarin/friendly-errors-webpack-plugin

一般在开发环境下使用。

var FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');

 

var webpackConfig = {

 // ...

 plugins: [

  new FriendlyErrorsWebpackPlugin(),

 ],

 // ...

}
Nach dem Login kopieren

效果如下图:

显示构建进度插件:webpack.ProgressPlugin

{

 // ...

 plugins: [

  new webpack.ProgressPlugin(),

 ],

 // ...

}
Nach dem Login kopieren

效果如下图:

美化 webpack 编译控制台打印的信息的插件webpack-dashboard

分离Webpack配置

将开发和生产配置文件分离,方便增加各个环境下的个性配置。Webpack2文档中也详细阐述了如何为多环境配置webpack。基本思路如下:

  1. 编写一个基本配置文件(webpack.base.config.js)

  2. 使用webpack-merge合并这个基础配置和针对环境的特定的配置(webpack.dev.config.js,webpack.prod.config.js)

webpack.base.config.js 内容如下:

var webpack = require('webpack');

var path = require('path');

var utils = require('./utils');

function resolve(relPath) {

  return path.resolve(__dirname, relPath);

}

module.exports = {

  entry: { app: resolve('../src/main.js') },

  output: {

    filename: 'js/[name].js'

  },

  module: {

    rules: [{

        test: /\.js$/,

        use: "babel-loader",

        include: [resolve('../src')]

      },

      {

        test: /\.vue$/,

        use: {

          loader: "vue-loader",

          options: utils.vueLoaderOptions()

        }

      },

      {

        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,

        use: {

          loader: "url-loader",

          options: {

            limit: 10000,

            name: 'images/[name].[hash:7].[ext]'

          }

        }

      },

      {

        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,

        use: [{

          loader: "url-loader",

          options: {

            limit: 10000,

            name: 'fonts/[name].[hash:7].[ext]'

          }

        }]

      }

    ]

  }

}
Nach dem Login kopieren

为什么要将vue-loader的options提取出来?其主要是用来配置CSS及CSS预处理语言的loader,开发环境可以不用配置,但是生产环境需要提取CSS、增加postcss-loader等,因此需要提取出来针对不同环境返回相应的options。后面会列出utils.vueLoaderOptions的内容。

为什么没有配置CSS的loader?理由和上面的vue-loader一样。

为什么没有配置path和publicPath?一方面是个性化参数,另外开发和生产可能不相同,因此在webpack.dev.config和webpack.prod.config中分别配置更为合适。

webpack.dev.config.js 内容如下:

var webpack = require('webpack');

var merge = require('webpack-merge');

var HtmlWebpackPlugin = require('html-webpack-plugin');

var baseWebpackConfig = require('./webpack.base.config');

var utils = require('./utils');

var config = require('./config');

Object.keys(baseWebpackConfig.entry).forEach(function(name) {

  baseWebpackConfig.entry[name] = [

    `webpack-dev-server/client?http://localhost:${config.dev.port}/`,

    "webpack/hot/dev-server"

  ].concat(baseWebpackConfig.entry[name])

});

module.exports = merge(baseWebpackConfig, {

  output: {

    path: config.dev.outputPath,

    publicPath: config.dev.outputPublicPath

  },

  module: {

    rules: utils.styleLoaders()

  },

  plugins: [

    new webpack.HotModuleReplacementPlugin(),

    new HtmlWebpackPlugin({

      filename: 'index.html',

      template: 'index.html',

      inject: true

    })

  ]

})
Nach dem Login kopieren

添加了HtmlWebpackPlugin后,index.html中就不需要在自己去引用打包的JS了,会自动根据打包的JS添加引用,这样更加方便,关于HtmlWebpackPlugin的配置,需要说明两点:

1.template的路径是相对于webpack编译时的上下文目录,说白了就是项目根目录,因此上面可以直接配置index.html,其指向的就是根目录下的index.html;

2.filename则是相对于webpack配置项output.path(打包资源存储路径)。

html-webpack-plugin关于template和filename路径源码如下:

// https://github.com/jantimon/html-webpack-plugin/blob/master/index.js

// template

this.options.template = this.getFullTemplatePath(this.options.template, compiler.context);

// filename

this.options.filename = path.relative(compiler.options.output.path, filename);
Nach dem Login kopieren

config.js内容如下:

module.exports = {

  dev: {

    outputPath: path.resolve(__dirname, '../static'),

    outputPublicPath: '/',

    port: 8000

  },

  prod: {

    outputPath: path.resolve(__dirname, '../static'),

    outputPublicPath: '/static/'

  }

}
Nach dem Login kopieren

utils.js内容如下:

var ExtractTextPlugin = require('extract-text-webpack-plugin');

var isProd = process.env.NODE_ENV === "production";

// 根据项目需求添加CSS预处理语言并安装相应的loader,以stylus-loader为例

var cssLang = [{

  name: 'css',

  reg: /\.css$/,

  loader: 'css-loader'

}, {

  name: 'stylus',

  reg: /\.styl$/,

  loader: "stylus-loader"

}];

function genLoaders(lang) {

  var loaders = ['css-loader', 'postcss-loader'];

  if (lang.name !== 'css') {

    loaders.push(lang.loader);

  }

  if (isProd) {

    // 生产环境需要提取CSS

    loaders = ExtractTextPlugin.extract({

      use: loaders

    });

  } else {

    // 开发环境需要vue-style-loader将CSS提取到页面头部

    loaders.unshift('vue-style-loader');

  }

  return loaders;

}

// 各种CSS的loader

exports.styleLoaders = function() {

  var output = [];

  cssLang.forEach(lang => {

    output.push({

      test: lang.reg,

      use: genLoaders(lang)

    })

  })

  return output;

};

// vue-loader的options

exports.vueLoaderOptions = function() {

  var options = {

    loaders: {}

  };

  cssLang.forEach(lang => {

    options.loaders[lang.name] = genLoaders(lang);

  });

  return options;

}
Nach dem Login kopieren

接下来就是如何启动webpack-dev-server,vue-cli的webpack模板工程用的express及webpack中间件做开发服务器,其实用webpack-dev-server就能满足需求,当然用express能够做更多的事情,毕竟webpack-dev-server是一个轻量级的express。dev.js内容如下:

var webpack = require('webpack');

var webpackDevServer = require('webpack-dev-server');

var devConfig = require("./webpack.dev.config");

var config = require("./config");

var compiler = webpack(devConfig);

var server = new webpackDevServer(compiler, {

  hot: true,

  noInfo: true,

  publicPath: config.dev.outputPublicPath,

  stats: { colors: true }

});

server.listen(config.dev.port, "0.0.0.0");

var url = `http://localhost:${config.dev.port}/`;

// 需先安装 opn 模块 npm i opn -D

var opn = require('opn');

// 打包完毕后启动浏览器

server.middleware.waitUntilValid(function() {

  console.log(`> Listening at ${url}`);

  opn(`${url}`);

})
Nach dem Login kopieren

生产配置文件(webpack.prod.config.js)内容如下:

// 设定为生产环境

process.env.NODE_ENV = 'production';

var webpack = require('webpack');

var merge = require('webpack-merge');

var HtmlWebpackPlugin = require('html-webpack-plugin');

var ExtractTextPlugin = require('extract-text-webpack-plugin');

var baseWebpackConfig = require('./webpack.base.config');

var utils = require('./utils');

var config = require('./config');

 

module.exports = merge(baseWebpackConfig, {

  output: {

    path: config.prod.outputPath,

    publicPath: config.prod.outputPublicPath

  },

  module: {

    rules: utils.styleLoaders()

  },

  plugins: [

    new webpack.DefinePlugin({

      'process.env.NODE_ENV': '"production"'

    }),

    new webpack.optimize.UglifyJsPlugin(),

    new ExtractTextPlugin({

      filename: "css/style.css?[contenthash:8]"

    }),

    new HtmlWebpackPlugin({

      filename: 'index.html',

      template: 'index.html',

      inject: true

    })

  ]

})
Nach dem Login kopieren

生产构建(prod.js)内容如下:

var webpack = require("webpack");

var webpackProdConfig = require('./webpack.prod.config');

webpack(webpackProdConfig, function(err, stats) {

  process.stdout.write(stats.toString());

});
Nach dem Login kopieren

对应在package.json中添加开发和生产构建的命令如下:

"scripts": {

  "dev": "node build/dev.js",

  "build": "node build/prod.js"

}
Nach dem Login kopieren

代码分割

参照vue-cli及webpack文档的提取公共代码的方式,利用插件webpack.optimize.CommonsChunkPlugin将来自node_modules下的模块提取到vendor.js(一般来讲都是外部库,短时间不会发生变化)。于是有如下代码:

new webpack.optimize.CommonsChunkPlugin({

  name: 'vendor',

  minChunks: function(module, count) {

    return module.resource && /\.js$/.test(module.resource) && module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0

  }

})
Nach dem Login kopieren

如果你查看未压缩版的vendor.js,会发现不仅包含vue的代码,还包含了webpackBootstrap(webpack模块加载器)的代码,按理说放在vendor里面也没啥问题,毕竟后面的模块都需要依赖于此,但是如果你的chunk使用了hash,一旦app代码发生了改变,相应的hash值会发生变化,webpackBootstrap的代码也会发生变化(如图),而我们提取vendor的初心就是这部分代码改变频率不大,显然这不符合我们的目标,那么应当将webpackBootstrap再提取到一个文件中,代码如下:

new webpack.optimize.CommonsChunkPlugin({

  name: 'manifest',

  chunks: ['vendor']

})
Nach dem Login kopieren

 

用 import 还是 require

vue 2.2.0 后不能直接使用 require 来加载 vue,那么到底改是该使用 ES6 Module 还是 CommonJS 呢?,先看一个对比图:

全部使用 ES6 Module,即import、export default,最终打包的app.js为1.20KB。

全部使用 CommonJS(除了vue),即require、module.exports,最终打包的app.js为1.12KB。

虽然两者大小相差不大,但是这不禁让人觉得用 CommonJS 似乎是一条优化措施,那么代码层面到底是怎么回事呢?

为了一探究竟,注释了压缩插件,以about.vue最终构建的代码来看,使用 CommonJS 的代码如下:

 (function (module, exports, __webpack_require__) {

 "use strict";

 module.exports = {

  data: function data() {

   return {

    page: 'about'

   };

  }

 };

}),
Nach dem Login kopieren

这基本上和 about.vue 中的代码相差无几,而使用 ES6 Module 构建的代码如下:

(function (module, exports, __webpack_require__) {

 "use strict";

 Object.defineProperty(exports, "__esModule", {

  value: true

 });

 exports.default = {

  data: function data() {

   return {

    page: 'about'

   };

  }

 };

}),
Nach dem Login kopieren

对比两种规范下构建后的代码,使用 ES6 Module 主要是多了 Object.defineProperty 那一部分,从而导致了最终打包的文件大一点儿。那是不是为了最终文件体积能小些就全部使用 CommonJS 呢?这个需要你充分理解 CommonJS 和 ES6 Module 的区别,引用《ECMAScript 6入门》这本书的解释如下:

ES6模块加载的机制,与CommonJS模块完全不同。CommonJS模块输出的是一个值的拷贝,而ES6模块输出的是值的引用。

为了更清楚的理解这段话,我们稍微做一下测试,在 src 下增加一个test.js,内容如下(分别将两种写法列出):
 

// CommonJS

var counter = 1;

function incCounter() {

  counter++;

}

module.exports = {

  counter: counter,

  incCounter: incCounter,

};

// ES6 Module

export let counter = 1;

export function incCounter() {

  counter++;

}
Nach dem Login kopieren

在about.vue中测试如下:

 // CommonJS

var test = require('../test');

export default {

  created() {

    console.log(test.counter); // 1

    test.incCounter();

    console.log(test.counter); // 1

  }

}

// ES6 Module

import { counter, incCounter } from '../test';

export default {

  created() {

    console.log(counter); // 1

    incCounter();

    console.log(counter); // 2

  }

}
Nach dem Login kopieren

最终的输出值也印证了前面的解释,更详细的解读请查阅相关资料或书籍。只有深入理解了两者的区别,自然就能明白何时该使用何种规范。当然 ES6 作为未来的趋势,我们应该去做更多的尝试。

异步组件(懒加载)

之前用懒加载的方式是:require.ensure,在 webpack2 中引入了 Code Splitting-Async 的新方法 import(),用于动态引入 ES Module。require.ensure 可以指定 chunkFilename,但是 import 没有很好的途径去指定,webpack3 为了解决这个问题,提出了用魔法注释的方式来指定模块名。

结合 vue-router 可以轻松实现懒加载,配置路由指向异步组件即可实现懒加载,比如:

{

    path: '/async',

    component: () => import(/* webpackChunkName: "async" */'./views/async.vue')

}
Nach dem Login kopieren

如果你发现使用 import() 运行时报错,有几种情况:
1.babel presets 配置为 es2015,则不支持动态导入功能,因此需要安装支持动态导入的 presets(npm i babel-preset-stage-2 -D),或者 babel 插件(npm i babel-plugin-syntax-dynamic-import -D);
2.babel presets 配置为 env,但是 modules 配置为 false,babel 则不会解析 import,可以安装插件 (npm i babel-plugin-syntax-dynamic-import -D)解决。

魔法注释虽然指定了块名,但是 webpack 默认的块名配置为 [id].js,即用的模块的 id 作为块名,因此需要我们手动改下配置。

修改 webpack.base.config.js 的 output:

output: {

  filename: 'js/[name].js',

  chunkFilename: "js/[name].[chunkhash].js"

}
Nach dem Login kopieren

效果如下图:

 

如果发现魔法注释没有生效,要检查下 .babelrc 的配置项 comments 是否设为 true。或者不配置 comments(默认为true)

extract-text-webpack-plugin 默认不会提取异步模块中的 CSS,需要加上配置:

new ExtractTextPlugin({

  allChunks:true,

  filename: "css/style.css?[contenthash:8]"

})
Nach dem Login kopieren

相关推荐:

webpack和vue2构建vue项目骨架讲解

关于vue2.0设置proxyTable使用axios进行跨域请求

简单了解vue2 单页面如何设置网页title

Das obige ist der detaillierte Inhalt vonTutorial zum Erstellen des vue2 vue-router2 webpack3-Projekts. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage