Maison > interface Web > js tutoriel > Création d'un didacticiel de projet vue2 vue-router2 webpack3

Création d'un didacticiel de projet vue2 vue-router2 webpack3

小云云
Libérer: 2018-01-16 09:13:20
original
1263 Les gens l'ont consulté

Cet article présente principalement l'explication détaillée de la construction du projet vue2 vue-router2 webpack3 à partir de zéro. L'éditeur pense qu'il est plutôt bon, je vais donc le partager avec vous maintenant et le donner comme référence. Suivons l’éditeur et jetons un coup d’œil. J'espère que cela aide tout le monde.

Du point de vue d'un novice, nous présenterons le contenu de chaque étape en détail. Nous n'entrerons pas dans les principes impliqués dans les étapes en profondeur, mais présenterons principalement comment fonctionner.

Initialisez le projet

Créez un nouveau répertoire de projet vue2practice, exécutez npm init -y dans le répertoire pour créer un package.json et ajoutez d'abord les modules nécessaires suivants à package.json :

{

 "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"

 }

}
Copier après la connexion

Parmi eux, vue-template-compiler est les peerDependencies de vue-loader. npm3 n'installera pas automatiquement les peerDependencies. Cependant, vue-template-compiler est nécessaire, alors pourquoi l'auteur ne le dit-il pas. dans les dépendances ? Quelqu'un a posé cette question sur github. Je vais traduire grossièrement la réponse de l'auteur (à titre de référence uniquement) : La raison en est qu'il n'existe aucun moyen fiable de corriger la relation des dépendances imbriquées. Tout d'abord, les numéros de version de vue-template-compiler et vue sont cohérents (actuellement mis à jour de manière synchrone). Spécifier vue-template-compiler comme dépendances de vue-loader ne garantit pas que les numéros de version de vue-template-compiler et vue sont les mêmes, permettre aux utilisateurs de spécifier la version peut garantir cela. Voir la réponse de l'auteur (en anglais). Si les deux versions sont incohérentes, le message d'erreur affiché dans la figure ci-dessous apparaîtra lors de l'exécution.

La nouvelle structure de répertoires est la suivante. Laissez d'abord les répertoires et fichiers nouvellement ajoutés vides. Les étapes suivantes expliqueront le contenu à ajouter.

vue2pratice

  |-- package.json

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

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

  |-- src

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

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

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

    |-- app.vue   // 工程首页组件
Copier après la connexion

Configuration de Webpack

Webpack lit webpack.config.js par défaut. Le nom du fichier ne peut pas être modifié avec désinvolture et l'entrée doit être configurée.

module.exports = {

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

  output: {

    path: __dirname + '/dist',

    publicPath: '/static/',

    filename: 'build.js'

  }

}
Copier après la connexion

Webpack 2+ nécessite que output.path soit un chemin absolu.

Pour configurer webpack-dev-server, ajoutez simplement la commande de démarrage suivante à package.json.

"scripts": {

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

}
Copier après la connexion

webpack-dev-server 2 est par défaut en mode en ligne, le remplacement du module à chaud doit toujours être configuré par vous-même.

Vérifiez la configuration

Ajoutez le code de test dans index.html et introduisez le fichier JS packagé.

<body>

  Hello, Webpack 3.

  <br>

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

</body>
Copier après la connexion

Ajouter le code de test dans main.js.

// main.js

document.write('来自main.js的问候!')
Copier après la connexion

Exécutez les commandes suivantes pour installer le module et démarrer le serveur.

// 安装依赖

npm install

 

// 运行

npm run dev
Copier après la connexion

Après le démarrage, le navigateur ouvrira automatiquement http://localhost:8080 Si aucune erreur n'est signalée dans la console, la page affichera correctement le contenu de main.js et index.html. Après avoir modifié main.js, le navigateur affichera l'effet sans actualiser, cela signifie qu'il n'y a aucun problème avec la configuration.

Vue

Nouvelle page

Créez un nouvel index.vue dans le répertoire des vues.

<template>

  <p>

    这是{{page}}页面

  </p>

</template>

<script>

export default {

  data: function () {

    return {

      page: 'index'

    }

  }

}

</script>
Copier après la connexion

webpack 1 nécessite un chargeur spécifique pour convertir l'import/export ES 2015, webpack 2 et supérieur peuvent être utilisés immédiatement. Cependant, la nouvelle syntaxe d'ES6 nécessite toujours la conversion du chargeur. N'utilisez pas la nouvelle syntaxe sans configuration. Aucune erreur n'est signalée après son utilisation (telle que let, const, etc.), car votre navigateur prend déjà en charge la syntaxe ES6 (les nouvelles versions des navigateurs la prennent déjà en charge).

Configuration du routage

Extraire le nouveau paramètre VueRouter (paramètre) transmis lorsque vue-router est instancié dans router.js pour former un fichier de configuration de routage.

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

export default {

  routes: [

    {

      path: '/index',

      component: index

    }

  ]

}
Copier après la connexion

Depuis vue-loader@13.0.0, vous ne pouvez pas utiliser require pour introduire des fichiers .vue, car les fichiers .vue seront éventuellement compilés dans des modules ES6.

Page d'accueil

La page d'accueil présente le JS de configuration de sortie et ajoute la cible de montage de l'instance Vue.

<body>

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

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

</body>
Copier après la connexion

L'entrée JS termine la configuration du routage et initialise l'instance Vue.

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)

});
Copier après la connexion

Si vous utilisez require('vue') à partir de Vue 2.2.0, une erreur sera signalée. Vous devez utiliser le module ES6 (importation). Pour des raisons spécifiques, veuillez vous référer à la mise à jour de Vue. instructions https://github.com/vuejs/ vue/releases, la capture d'écran est la suivante :

Ajouter des liens de routage et des composants de vue de routage au composant de page d'accueil app.vue .

<template>

  <p>

    <p>

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

    </p>

    <p>

      <router-view></router-view>

    </p>

  </p>

</template>
Copier après la connexion

Configurer le chargeur

Configurer le chargeur correspondant au fichier vue.

module: {

  rules: [

    {

      test: /\.vue$/,

      use: ["vue-loader"]

    }

  ]

}
Copier après la connexion

Webpack2 doit configurer le chargeur sous module.rules. '-loader' ne peut pas être omis, le nom du chargeur doit être écrit en entier. Vous pouvez utiliser Rule.use ou Rule.loader pour configurer le chargeur (Rule.loader est l'abréviation de Rule.use : [ {loader } ]).

Ce qui précède a terminé la configuration requise pour ajouter une nouvelle page et accéder à la page. Testons maintenant si /index est accessible normalement. Exécutez npm run dev et le navigateur affichera l'interface comme indiqué sur la figure.

Support CSS

Vous pouvez l'utiliser dans les fichiers vue après avoir installé css-loader

npm i css-loader -D
Copier après la connexion

Vous souhaitez prendre en charge l'importation/exiger Lors de l'introduction de fichiers CSS, vous devez configurer la règle correspondante.

{

  test: /\.css$/,

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

}
Copier après la connexion
<script>

import "../style/style.css"

</script>
Copier après la connexion

Prise en charge du langage de prétraitement CSS

Prenez le stylet comme exemple, installez le stylet et le chargeur de stylet.

npm install stylus stylus-loader -D
Copier après la connexion

Ajoutez la configuration du chargeur correspondant au fichier .styl.

{

  test: /\.styl$/,

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

}
Copier après la connexion

Exemple d'utilisation :

<style lang="stylus">

  .stylus

    .red

      color red

</style>

<script>

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

</script>
Copier après la connexion

Solution pour ralentir l'installation de node-sass

Utiliser le miroir Taobao :

npm set disturl https://npm.taobao.org/dist
Copier après la connexion

Vous pouvez également définir l'image node-sass séparément :

npm set sass_binary_site http://cdn.npm.taobao.org/dist/node-sass
Copier après la connexion

Prend en charge les polices d'images et d'icônes

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

npm install url-loader file-loader -D
Copier après la connexion

增加图片及图标字体的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文件夹下

    }

  }]

}
Copier après la connexion

构建

添加打包命令如下:

"build":"webpack --progress --colors"
Copier après la connexion

执行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
Copier après la connexion

增加babel的配置文件.babelrc。

{

  "presets": [

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

  ],

  "comments": false

}
Copier après la connexion

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

comments 即是否保留注释。

接着配置 JS 文件的 loader。

{

  test: /\.js$/,

  use: "babel-loader",

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

}
Copier après la connexion

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

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

new webpack.optimize.UglifyJsPlugin()
Copier après la connexion

官网称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
Copier après la connexion
// 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"]

  })

}
Copier après la connexion

上述配置并不能提取 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"]

        })

      }

    }

  }

}
Copier après la connexion

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

new ExtractTextPlugin({

  filename: "css/style.css"

})
Copier après la connexion

PostCSS

安装 postcss-loader 及 postcss 插件。

npm i postcss-loader cssnano -D
Copier après la connexion

配置 loader 如下:

// css-loader配置改为

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

// stylus-loader配置改为

use: ["css-loader", "postcss-loader", "stylus-loader"]
Copier après la connexion

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')

  ]

}
Copier après la connexion

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

require('cssnano')({

  autoprefixer: {

    add: true,

    browsers: ['> 5%']

  }

})
Copier après la connexion

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

require('cssnano')({

  zindex: {

    disable:true

  }

})
Copier après la connexion

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

生成首页

安装 html-webpack-plugin 插件。

npm i html-webpack-plugin -D
Copier après la connexion

初始化插件。

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

new HtmlWebpackPlugin({

  filename: 'index.html',

  template: 'index.tpl.html'

})
Copier après la connexion

其它插件

Webpack3 新增的作用域提升。

new webpack.optimize.ModuleConcatenationPlugin()
Copier après la connexion

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

new webpack.DefinePlugin({

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

})
Copier après la connexion

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

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

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

  // 开发环境

}

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

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

  // 开发环境

}

// 输出

if (false) {

  // 开发环境

}

// UglifyJS 会删除这段无效代码
Copier après la connexion

使用上述插件后再次构建,会发现生成的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(),

 ],

 // ...

}
Copier après la connexion

效果如下图:

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

{

 // ...

 plugins: [

  new webpack.ProgressPlugin(),

 ],

 // ...

}
Copier après la connexion

效果如下图:

美化 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]'

          }

        }]

      }

    ]

  }

}
Copier après la connexion

为什么要将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

    })

  ]

})
Copier après la connexion

添加了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);
Copier après la connexion

config.js内容如下:

module.exports = {

  dev: {

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

    outputPublicPath: '/',

    port: 8000

  },

  prod: {

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

    outputPublicPath: '/static/'

  }

}
Copier après la connexion

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;

}
Copier après la connexion

接下来就是如何启动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}`);

})
Copier après la connexion

生产配置文件(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

    })

  ]

})
Copier après la connexion

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

var webpack = require("webpack");

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

webpack(webpackProdConfig, function(err, stats) {

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

});
Copier après la connexion

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

"scripts": {

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

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

}
Copier après la connexion

代码分割

参照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

  }

})
Copier après la connexion

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

new webpack.optimize.CommonsChunkPlugin({

  name: 'manifest',

  chunks: ['vendor']

})
Copier après la connexion

 

用 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'

   };

  }

 };

}),
Copier après la connexion

这基本上和 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'

   };

  }

 };

}),
Copier après la connexion

对比两种规范下构建后的代码,使用 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++;

}
Copier après la connexion

在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

  }

}
Copier après la connexion

最终的输出值也印证了前面的解释,更详细的解读请查阅相关资料或书籍。只有深入理解了两者的区别,自然就能明白何时该使用何种规范。当然 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')

}
Copier après la connexion

如果你发现使用 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"

}
Copier après la connexion

效果如下图:

 

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

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

new ExtractTextPlugin({

  allChunks:true,

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

})
Copier après la connexion

相关推荐:

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

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

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal