首页 > 代码库 > webpack2配置

webpack2配置

详细的配置可以参考官网:https://doc.webpack-china.org/guides/

一开始做项目时都是直接从组里前辈搭建好的脚手架开始写代码,到后来自己写新项目时又是拷贝之前的工程作为脚手架开始。对于脚手架本身却不甚了解,不仅不思考为什么更是没有改进的想法,怪不得工作满一年了却总觉得自己的技术水平在原地踏步,就是没有总结和思考。

目前组里的技术栈都是使用vue+koa,使用webpack的好处一是方便写vue的单文件组件,二是打包文件方便生产部署再加上能无所顾虑的应用语言的新特性。

1. 配置文件

官方文档推荐写webpack配置文件时,先写出一个基本配置文件包含入口、输出等,再根据开发/生产环境所需要插件的不同,利用webpack-merge生成两个配置文件。

package.json 依赖参考

"devDependencies": {
    "babel-core": "^6.25.0",
    "babel-loader": "^7.1.1",
    "css-loader": "^0.28.4",
    "less": "^2.7.2",
    "less-loader": "^4.0.4",
    "style-loader": "^0.18.2",
    "vue-loader": "^13.0.0",
    "webpack": "^3.0.0",
    "webpack-chunk-hash": "^0.4.0",
    "webpack-dev-server": "^2.5.0",
    "webpack-manifest-plugin": "^1.1.2",
    "webpack-merge": "^4.1.0"
  }

 

webpack.config.base.js

 1 const path = require(‘path‘);
 2 const webpack = require(‘webpack‘);
 3 const WebpackManifestPlugin = require("webpack-manifest-plugin");
 4 const WebpackChunkHash = require("webpack-chunk-hash");
 5 
 6 module.exports = {
 7     entry: {
 8         index: ‘./app/src/index.js‘,
 9     },
10     output: {
11         path: path.resolve(__dirname, ‘..‘, ‘app‘, ‘public‘, ‘js‘)
12     },
13     resolve: {
14         alias: {
15             ‘vue$‘: path.resolve(__dirname, ‘../node_modules/vue/dist/vue.js‘),
16         }
17     },
18     module: {
19         loaders: [
20             {
21                 test: /\.vue$/,
22                 loader: ‘vue-loader‘,
23             },
24             {
25                 test: /\.js$/,
26                 exclude: /node_modules/,
27                 loader: ‘babel-loader‘,
28             },
29             {
30                 test: /\.css$/,
31                 use: [ ‘style-loader‘, ‘css-loader‘ ]
32             },
33             {
34                 test: /\.less$/,
35                 loader: "style!css!less"
36             }
37         ]
38     },
39     plugins: [
40         new WebpackManifestPlugin(),
41         new webpack.optimize.CommonsChunkPlugin({
42             name: ‘vendor‘,
43             minChunks: function (module) {
44                 // this assumes your vendor imports exist in the node_modules directory
45                 return module.context && module.context.indexOf(‘node_modules‘) !== -1;
46             }
47         }),
48         //CommonChunksPlugin will now extract all the common modules from vendor and main bundles
49         new webpack.optimize.CommonsChunkPlugin({
50             name: ‘manifest‘ //But since there are no more common modules between them we end up with just the runtime code included in the manifest file
51         }),
52         new WebpackChunkHash(),
53     ],
54 }

第15行代码可以参考这里和这里,默认NPM包导出的是运行时构建,Vue2的运行时构建不支持单文件组件的template

第40行的 WebpackManifestPlugin 作用是将输出文件名保存在文件中 (当输出文件名带 chunkhash 时很有用,参考这里)

第41、49行的 CommonsChunkPlugin 作用是从打包后的 bundle 文件中提取公共模块,将 npm install 的公共模块和业务代码分开,这样浏览器就可以一直缓存公共模块的bundle,参考这里

第52行的 WebpackChunkHash 作用是让文件名的哈希值基于文件内容

 

webpack.config.dev.js

 1 const path = require(‘path‘);
 2 const webpack = require(‘webpack‘);
 3 const Merge = require(‘webpack-merge‘);
 4 const baseConfig = require(‘./webpack.config.base.js‘);
 5 
 6 module.exports = Merge(baseConfig, {
 7     output: {
 8         filename: ‘[name].js‘,
 9     },
10     devtool: ‘#eval-source-map‘,
11     plugins: [
12         new webpack.HotModuleReplacementPlugin()
13     ],
14     devServer: {
15         port: 7002,
16         hot: true
17     }
18 });

第10行设置source-map,方便用浏览器查看源代码

第12、14行主要用于使用下面会提到的webpack-dev-server

 

webpack.config.prod.js

 1 const webpack = require(‘webpack‘);
 2 const Merge = require(‘webpack-merge‘);
 3 const baseConfig = require(‘./webpack.config.base.js‘);
 4 
 5 module.exports = Merge(baseConfig, {
 6     output: {
 7         filename: ‘[name].[chunkhash].js‘,
 8     },
 9     plugins: [
10         new webpack.optimize.UglifyJsPlugin({
11             compress: {
12                 warnings: false
13             }
14         })
15     ]
16 });

第10行 UglifyJsPlugin 的作用是压缩、混淆代码

webpack的配置文件自定义程度很高,所以在参考他人配置时最好能弄清楚为什么要这样写

 

2. webpack-dev-server 

在开发过程中另一个重要的东西是 webpack-dev-server,它的作用是当你改动源代码后能自动重新打包,再加上 webpack 的HMR-模块热替换特性,这样改动代码就能直接在浏览器里看到效果,省却了代码手动打包+刷新浏览器的步骤。使用 webpack-dev-server 有 CLI 和 API 两种使用方法。

CLI 也就是我目前所用的方法,需要设置好配置文件,参考上面的 dev 文件中的 HotModuleReplacementPlugin 和 devServer 设置:devServer 的port 为 webpack-dev-server 运行的端口,hot 设置和 HotModuleReplacementPlugin 启用 HMR。启动的命令为:

node_modules/.bin/webpack-dev-server --config ./config/webpack.config.dev.js

然后通过 http://localhost:7002/index.js 就能获取到打包后对应的文件内容,注意文件是在内存,端口和文件名参考配置文件。

要想在网页中引用打包后的文件可以通过后端使用 nunjucks 之类的模板将文件地址注入到网页中,这里有好几个需要注意的地方。

一个是打包后的 bundle 文件需要注意引入的顺序,公共模块文件要先引入进来,我的开发环境引入顺序为:

<script src="http://localhost:7002/manifest.js"></script>
<script src="http://localhost:7002/vendor.js"></script>
<script src="http://localhost:7002/index.js"></script>

否则会报 ReferenceError: webpackJsonp is not defined 错误

二是注意要有 .babelrc 文件:

{
    "presets": ["es2015"]
}

否则会报 SyntaxError: Unexpected token: name (xxxxxx) from Uglify plugin 之类的错误,无法识别语言新特性

三是在生成环境中,由于输出文件的文件名带 chunkhash,会随着文件内容的改变而改变,所以需要在后端读取 manifest.json 文件的内容,并将文件名通过 nunjucks 之类的模板引擎注入到网页中。当然可以不使用 chunkhash,这样就可以将文件名在网页里写死了,但这样就不方便利用到浏览器的缓存。

API 方法的使用可参考 这里 和 这里

 

3. webpack-dev-middleware

当使用 express、koa 之类的后端框架时可以利用 webpack-dev-middleware,通过中间件来实现热加载。具体使用方法:这里

webpack2配置