webpack 配置
webpack 3.6.0
build 目录
webpack.base.conf.js
webpack.dev.conf.js
webpack.prod.conf.js
webpack.test.conf.js
分别对应着公共配置项、开发、生产和测试环境的配置。然后使用webpack-merge把这些公共配置项和环境特定的配置项merge起来,成为一个完整的配置项。
'use strict'
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const devWebpackConfig = merge(baseWebpackConfig, {
...
})
这三个环境不仅有一部分配置不同,更关键的是,每个配置中用 webpack.DefinePlugin 向代码注入了 NODE_ENV 这个环境变量。
这个变量在不同环境下有不同的值,比如 dev 环境下就是 development。这些环境变量的值是在 config 文件夹下的配置文件中定义的。Webpack 首先从配置文件中读取这个值,然后注入。比如这样:
// build/webpack.dev.conf.js
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env.js')
}),
]
// config/dev.env.js
module.exports ={
NODE_ENV: '"development"'
}
这种区分不同的环境,并给环境变量设置不同的值的实践,让我们开启了编译时按环境对代码进行针对性优化的可能。
html在webpack中的配置
以commonJS模块化机制向外输出
//在webpack.base.conf.js中的配置
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
HTML打包我们需要安装引入html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 在module.exports里配置我们的plugins(插件):
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({ //将模板的头部和尾部添加css和js模板,dist 目录发布到服务器上,项目包。可以直接上线
filename: 'index.html',
template: 'index.html',
inject: true
}),
]
配置好后,在终端输入npm run dev后webpack将我们的html打包好并且自动将我们的js引进来
css在webpack的配置
extract-text-webpack-plugin
在执行npm run build之后并没有我们的css,因为webpack配置里 css in js。即打包时是吧我们的css打包进js里的。所以引入extract-text-webpack=p;ugin插件将css从js里面剥离出来.
require机制:在我们打包的过程中,文件的引用require按照顺序来打包。这就是文件依赖的机制。
js在webpack中的配置
由于很多浏览器并不支持es6.所以需要引用babel将es6代码编译成es5.
1. 新建.babelrc文件进行配置。
2. 安装babel并在webpack.config.base.js里的modules/rules下进行配置
babel-loader babel-core babel-preset-env //babel基本的三个文件
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
图片资源在webpack中的配置
- src目录下新建一个assets文件放置图片。安装file-loader根据文件地址加载文件
- 在webpack.config.base.js里的module/rules
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
别名(@)在webpack中的配置
在vue-cli中我们经常@一个文件夹,其意思就是在src目录下,现在我们去一探究竟。在exports下,注意跟module同级。
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'src': path.resolve(__dirname, '../src'),
'common': path.resolve(__dirname, '../src/common'),
'components': path.resolve(__dirname, '../src/components')
}
},
其他一些静态资源在webpack中的配置
src下其他的文件直接复制到dist目录下,并不是每个文件都需要打包处理的,很多资源可能直接就可以复制过去。使用我们的 CopyWebpackPlugin插件
引用框架 jquery lodash工具库是很多组件会复用的,省去了import。使用webpack.ProvidePlugin插件
npm run dev 发生了什么
在vue-cli中我们启动监听npm run dev可以时时监控我们src下文件的改动,那他到底发生了什么呢。在webpack里其实创建了一个node进程,通过webpack-dev-server其内部封装了一个node的express模块,其配置项如下:
//package.json中的配置
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"lint": "eslint --ext .js,.vue src",
"build": "node build/build.js"
},
//webpack.dev.conf.js中的配置
devServer: {
before(app) {
app.get('/api/seller', function(req, res) {
res.json({
errno: 0,
data: seller
})
});
app.get('/api/goods', function(req, res) {
res.json({
errno: 0,
data: goods
})
});
app.get('/api/ratings', function(req, res) {
res.json({
errno: 0,
data: ratings
})
});
}, 服务于webpack-dev-server 内部封装了一个express
webpack4 的变化
详细可见:https://juejin.im/post/5b304f1f51882574c72f19b0
开发和生产环境的区分
Webpack4引入了mode这个选项。这个选项的值可以是development或者production.
设置了 mode 之后会把 process.env.NODE_ENV 也设置为 development 或者 production。然后在 production 模式下,会默认开启 UglifyJsPlugin 等等一堆插件
Webpack 4 下如果需要一个 test 环境,那 test 环境的 mode 也是 development。因为 mode 只有开发和生产两种,测试环境应该是属于开发阶段。
Code Splitting
Webpack 4 下还有一个大改动,就是废弃了 CommonsChunkPlugin,引入了 optimization.splitChunks 这个选项。
optimization.splitChunks 默认是不用设置的。如果 mode 是 production,那 Webpack 4 就会开启 Code Splitting。
默认 Webpack 4 只会对按需加载的代码做分割。如果我们需要配置初始加载的代码也加入到代码分割中,可以设置 splitChunks.chunks 为 'all'。
Long-term caching
Long-term caching 这里,基本的操作和 Webpack 3 是一样的。不过 Webpack 3 的 Long-term caching 在操作的时候,有个小问题,这个问题是关于 chunk 内容和 hash 变化不一致的:
在公共代码 Vendor 内容不变的情况下,添加 entry,或者 external 依赖,或者异步模块的时候,Vendor 的 hash 会改变。
Webpack 内部维护了一个自增的 id,每个 chunk 都有一个 id。所以当增加 entry 或者其他类型 chunk 的时候,id 就会变化,导致内容没有变化的 chunk 的 id 也发生了变化。
应对方案是,使用 webpack.NamedChunksPlugin 把 chunk id 变为一个字符串标识符,这个字符包一般就是模块的相对路径。这样模块的 chunk id 就可以稳定下来