(1)使用相同的配置文件,在构建开始前将当前所属环境作为一个变量传递进去,在webpack.config.js中通过各种判断条件决定具体使用哪个配置。
//package.json
{
'script': {
'dev': "ENV=development webpack-dev-server",
'build': 'ENV=production webpack'
}
}
//webpack.config.js
const ENV = process.env.Env;
const isProd = ENV === 'production';
module.exports = {
output: {
filename: isProd ? 'bundle@[chunkhash].js' : 'bundle.js'
},
mode: ENV
}
(2)为不同的环境创建各自的配置文件。
//package.json
{
'script': {
'dev': "webpack-dev-server --config=webpack.development.config.js",
'build': 'webpack --config=webpack.production.config.js'
}
}
1、需要将公共的配置提取出来,比如单独创建一个webpack.common.config.js。
2、使用webpack-merge
//导入基础配置
const comminConfig = require('./webpack.common.config.js');
//merge插件
const merge = require('webpack-merge');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
//当前配置结合base配置
module.exports = merge.smart(comminConfig, {
mode: 'production',
modules: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extarct({
fallback: 'style-loader',
use: 'css-loader'
})
}
]
}
});
它在合并module.rules的过程中会以test属性作为标识符,当发现有相同项出现的时候会以后面的规则覆盖前面的规则,这样就不必添加冗余代码了(对比使用Obejct.assign,必须替换掉整个modules)
使用DefinePlugin进行设置。
const webpack = require('webpack')
module.exports = {
entry: {
app: './app.js',
},
mode: 'production',
plugins: [
new webpack.DefinePlugin({
ENV: JSON.stringify('production'),
}),
]
}
1、除了字符串类型的值外,还可以设置其他类型的环境变量。
2、许多框架和库都采用process.env.NODE_ENV作为一个区分开发环境和生成环境的变量。
prcoess.env是Node.js用于存放当前进程环境变量的对象,而NODE_ENV则可以让开发者指定当前的运行环境。
new webpack.DefinePlugin({
process.env.NODE_ENV: 'production',
}),
如果启用了mode:production,则webpack已经设置好了process.env.NODE_ENV,不需要再人为添加了。
(1)source map指的是将编译、打包、压缩后的代码映射回源代码的过程。
(2)工作原理
1、webpack对于工程源代码的每一步处理都有可能会改变代码的位置、结构、甚至是所处文件,因此每一步都需要生成对应的source map。
2、若我们启用了devtool配置项,source map就会跟随源代码一步步被传递,直到生成最后的map文件。
3、这个文件默认就是打包后的文件名加上.map如:bundle.js.map。
4、在生成mapping文件的同时,bundle文件中会追加一句注释来表示map文件的位置
//bundle.js
(function(){))()
//#sourceMappingURL=bundle.js.map
5、当我们打开浏览器的开发者工具时,map文件会同时被加载,这时浏览器会使用它来对打包后的bundle文件进行解析,分析出源代码的目录结构及内容。
(3)map文件有时会很大,但是不用担心,只要不打开开发者工具,浏览器是不会加载这些文件的,因此对于普通用户没有影响。但是使用source map会有一定的安全隐患,即任何人都可以通过dev tools看到工程源码。
(4)source map配置
module.exports = {
//....
devtool: 'source-map'
}
对于CSS、SCSS、Less来说,则需要添加额外的 source map 配置项。
(5)开启source map之后,打开chorme的开发者工具,在’Sources‘选项卡下面“webpack://”目录中可以找到解析后的工程源码。
(6)其他形式
1、source map
2、cheap-source-map(source map简略版本,开发环境是个不错的选择)
3、eval-source-map(source map简略版本)
(7)安全
1、hidden-source-map:意味着webpack仍然会产出完整的map,不过不会再bundle文件中添加对于map文件的引用。如果想要追溯源码,需要利用一些第三方服务,将map文件上传到那上面。(如Sentry)
2、nosources-source-map:打包部署后,在浏览器开发者工具中可以看到源码的目录结构,但是具体文件内容会被隐藏起来。对于错误来说,我们仍然可以在consle控制中查看源码的错误栈,或者console日志的准确行数。
3、nginx服务器设置白名单。
(1)压缩Javascript
module.exports = {
entry: {
app: './app.js',
},
plugins: [
new webpack.optimize.UglifyJsPlugin()
]
}
支持ES6+代码的压缩,更加面向与未来。(如果开启了mode:production,则不需要人为设置)
const webpack = require('webpack')
module.exports = {
entry: {
app: './app.js',
},
optimization: {
minimize: true
}
}
(2)压缩CSS
1、前提使用extract-text-webpack-plugin或mini-css-extract-plugin将样式提取出来。然后使用optimize-css-assets-webpack-plugin进行压缩。(这个插件本质上使用的是压缩器cssnano)
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extarct({
fallback: 'style-loader',
use: 'css-loader'
})
}
]
},
plugins: [
new ExtractTextPlugin('styles.css'),
],
optimization: {
minimizer: [new OptimizeCSSAssetsPlugin({
//生效范围,只压缩匹配到的资源
assetNameRegExp: /\.css$/g,
//压缩处理器,默认为cssnano
cssProcessor: require('cssnano'),
//压缩处理器的配置
cssProcessorPluginOptions: {
preset: ['default', { discardComments: { removeAll: true } }],
},
//是否展示log
canPrint: true
}),]
}
};
(1)资源hash
通常使用chunkhash来作为文件版本号,因为它会为每一个chunk单独计算一个hash。每当代码发生变化时相应的hash也会发生变化。
module.exports = {
output: {
filename: 'bundle@[chunkhash].js'
},
}
(2)输出动态HTML
1、资源名改变后需要将HTML中的引用路径进行改变。
2、html-webpack-plugin:在打包结束后自动把最新的资源名同步过去。
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin(),
],
}
传入一个已有的html模板
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: './template.html'
}),
],
}
(3)使chunk id更稳定
1、webpack3中使用ComminChunkPlugin,可能存在问题。webpack为每个模块指定的id是按数字递增的,当有新的模块插入进来时会导致其他模块的id也发生变化,进而影响了vendor chunk 中的内容。
2、解决方法在于更改模块id的生成方式,webpack3中内部自带了HashedModuleIds-Plugin,它可以为每个模块按照其所在路径生成一个字符串类型的hash id。
3、对于webpack3以下的版本,由于其不支持字符串类型的模块id,可以使用另外一个社区提供的兼容性插件webpack-hashed-module-id-plugin。
4、webpack4以后已经修改了模块id的生成机制,也就不再有该问题了。