webpack开发环境和生产环境的深入理解
以前自己写一小项目时,webpack的配置基本就是一套配置,没有考虑生产环境和开发环境的区分,最近在做一个复杂的商城项目接触到了webpack的高级配置,经过两天的研究,写出了一份目前来说比叫满意的配置,在这里分享一下。
如何区分开发环境和生产环境?
众所周知,webpack时基于node.js平台运行的,要区分开发环境和生产环境还要存,node入手。我们启动webpack时,都需要输入一些命令,npmrun、yarnstart之类的,所以我们就从命令行入手,告诉webpack,当前是什么环境。
package.json
{
"name":"webpac-demo",
"version":"1.0.0",
"description":"webpack练习",
"main":"index.js",
"scripts":{
//配置开发环境参数。注意:真实开发中package.json文件中不能有注释
"dev":"webpack--env=development",
//配置生产环境参数
"dist":"webpack--env=production",
"start":"webpack-dev-server--env=development"
},
"dependencies":{
"font-awesome":"^4.7.0",
"react":"^16.2.0",
"react-dom":"^16.2.0"
},
"devDependencies":{
...
}
}
这样配置,当我们在命令行输入npmrundev和npmrundist时,就会附带一些参数到命令行中,有了参数,我们该如何拿到呢?那就要用到node的一个命令行参数解析引擎了。
minimist
minimist轻量级的命令行参数解析引擎
//test.js
varargs=require('minimist')(process.argv.slice(2));
console.log(args.hello);
$nodetest.js--env=production
//production
$nodetest.js--env=development
//development
$nodetest.js--env
//true注意:不是空字符串而是true
minimist会把参数解析成一个JSON对象:{key:value},有了这个JSON对象,我们就可以知道,当前的命令是要执行开发打包,还是生产打包了。
//webpack.config.js
constwebpack=require('webpack');
//当前项目的绝对路劲
constpath=require('path');
//命令行参数解析引擎
constargv=require('minimist')(process.argv.slice(2));
letenv=null;
switch(argv.env){
case'production':
//生产环境配置文件名
env='webpack.config.prod';
break;
default:
//开发环境配置文件名
env='webpack.config.dev';
}
console.log(`当前是${argv.env}打包`);
//这时候,我们就可以加载相应的wabpack配置了。
module.exports=require(path.resolve('加载的配置文件路劲',env));
webpack开发环境配置和生产环境配置
开发环境配置
在开发环境下,我们首先考虑的是方便开发,方便代码调试,不需要考虑代码合并和css样式分离这些。
这里主要说三个:1.css模块化;2.模块热替换功能;3.source-map(代码映射)
//开发环境打包配置
constpath=require('path');
constwebpack=require('webpack');
constbase=require('./webpack.config.base')
constdfPath=require('./path')
//webpack配置合并工具
constmerge=require('webpack-merge')
constRS=(...arg)=>path.resolve(__dirname,...arg)
//合并方式配置
letstrategyMerge=merge.strategy({
entry:'prepend'
});
letconfig={
entry:{
app:path.resolve(dfPath.root,'src/app.js')
},
output:{
path:dfPath.dist,
filename:'[name].bundle.js',
publicPath:'/',
chunkFilename:'[name].sepChunk.js'
},
module:{
rules:[
{
test:/\.js$/,
use:['babel-loader'],
exclude:[
dfPath.node_modules
]
},
{
test:/\.css$/,
use:[
'style-loader',
{
loader:'css-loader',
options:{
//css模块化,方便多人开发
module:true,
//定义模块化css后的类名(默认为hash值,可读性差)path:路劲;name:文件名;local:本地定义的className
localIdentName:'[path][name]__[local]--[hash:base64:5]'
},
}
],
//排除的文件,遇到这些文件不会用当前loader处理,也就不会模块化
exclude:[
RS('./src/common'),
RS('node_modules')
]
},
{
test:/\.css$/,
use:['style-loader','css-loader'],
include:[
RS('./src/common'),
RS('node_modules')
]
},
{
test:/\.(png|jpg|jpeg|gif)$/,
use:['url-loader?limit=8192'],
}
]
},
plugins:[
//模块热替换功能
newwebpack.HotModuleReplacementPlugin()
],
//代码映射,方便报错时,找到对应的源代码
devtool:'cheap-module-eval-source-map',
devServer:{
//服务器打包后,输出的资源路劲
publicPath:'/',
open:true
}
};
//导出合并后的webpack配置
module.exports=strategyMerge(base,config);
生产环境配置
相比开发环境,生产环境打包是要最后发布到服务器部署的代码,我们需要尽量保持代码简洁,加载性能最优,不需要调试辅助工具。
我们从这几个方面优化:1.公共模块拆分,单独打包;2.css文件分离,单独打包输出;3.代码压缩;
//生产环境配置
constwebpack=require('webpack');
constbase=require('./webpack.config.base')
constpath=require('path');
constdfPath=require('./path');
constmerge=require('webpack-merge');
//压缩工具
constClosureCompilerPlugin=require('webpack-closure-compiler');
//css单独打包插件
constextractTextWebpackPlugin=require('extract-text-webpack-plugin');
constextractCSS=newextractTextWebpackPlugin('assets/css/[name]_[contenthash:6].css');
//weback合并配置
letstrategyMerge=merge.strategy({
entry:'replace',
output:'replace',
module:{
rules:'replace'
}
});
letconfig={
entry:{
//公共模块拆分,这些代码会单独打包,一般我们会把引用的框架文件拆分出来,方便浏览器缓存,节省资源。
vender:['react'],
app:path.resolve(dfPath.root,'src/app.js')
},
output:{
path:dfPath.dist,
filename:'assets/js/[name]_[chunkhash].bundle.js',
publicPath:'/',
chunkFilename:'assets/js/[name].sepChunk.js',
hashDigestLength:6
},
module:{
rules:[
{
test:/\.js$/,
use:['babel-loader'],
exclude:[
dfPath.node_modules
]
},
/*开启css单独打包和css模块化的配置*/
{
test:/\.css$/,
use:extractCSS.extract({
use:[
{
loader:'css-loader',
options:{
modules:true
}
}
]
})
},
{
test:/\.(png|jpg|jpeg|gif)$/,
use:[
{
loader:'url-loader',
options:{
limit:8192,
name:'[name]_[hash].[ext]',
outputPath:'assets/img/'
}
}
],
},
{
test:/\.(mp4|ogg|svg|ico)$/,
use:[
{
loader:'file-loader',
options:{
name:'[name]_[hash].[ext]',
outputPath:'assets/media/'
}
}
]
},
{
test:/\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
use:[
{
loader:'url-loader',
options:{
limit:10000,
name:'[name]_[hash].[ext]',
outputPath:'assets/font/',
mimetype:'application/font-woff'
}
}
]
},
{
test:/\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use:[
{
loader:'url-loader',
options:{
limit:10000,
name:'[name]_[hash].[ext]',
outputPath:'assets/font/',
mimetype:'application/octet-stream'
}
}
]
},
{
test:/\.eot(\?v=\d+\.\d+\.\d+)?$/,
use:[
{
loader:'file-loader',
options:{
name:'[name]_[hash].[ext]',
outputPath:'assets/font/',
}
}
]
},
{
test:/\.svg(\?v=\d+\.\d+\.\d+)?$/,
use:[
{
loader:'url-loader',
options:{
limit:10000,
name:'[name]_[hash].[ext]',
outputPath:'assets/font/',
mimetype:'image/svg+xml'
}
}
]
},
]
},
plugins:[
extractCSS,
//设置process.env(生产环境)环境变量的快捷方式。
newwebpack.EnvironmentPlugin({
NODE_ENV:'production'
})
,newClosureCompilerPlugin()
],
devtool:'source-map'
};
module.exports=strategyMerge(base,config);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。