前言:webpack4从入门到高阶配置,本文先讲述webpack4的安装、基础配置、进阶配置,高阶配置放置下篇讲述。
一、webpack4(4.8版本)与之前版本的区别
1、webpack4拆分出了webpack和webpack-cli,所以需安装这两个;
2、实现了零配置,默认的入口为'./src',默认的出口为'./dist'
3、新增mode参数,分为development(开发环境)和producution(生产环境);
4、公共代码提取:废除了CommonsChunkPlugin插件,使用optimazation.splitChunksPlugin参数代替
二、安装
1、全局安装:npm install --save webpack webpack-cli
2、局部安装:即进入项目目录安装webpack、webpack-cli(推荐),如全局安装,因版本不同,不便于维护
3、使用npm init初始化package.json(需要在webpack及webpack-cli安装后在初始化package.json,否则会报错)
4、根目录下创建webpack.config.js配置文件,如目录结构图,配置文件的具体配置内容将在基础配置中讲述
项目目录结构如下(.idea、webpack.iml为编辑器自带文件)
三、打包运行的命令(以下命令只能在命令行或者终端运行)
1、webpack自带命令
webpack entry.js output.js
entry.js为入口文件,即需要打包文件所在的路径
output.js为输出文件,即打包生成的文件所放置的目录
例:
webpack './src/js/index.js' './dist/js/index.bundle.js’
2、使用npm配置,需在package.json的scripts中配置
"scripts": {
"start": "webpack"
},
//命令行或终端运行npm start即可打包文件,start也可改成其他名称
四、基础配置
webpack.config.js主要配置分为7个部分:mode、entry、output、module、plugins、devSever、optimization,整体内容格式如下:
module.exports={
mode:’’,
entry:{},
output:{},
module:{
rules:[]
},
plugins:[],
devSever:{},
optimization:{}
}
//并不是每一个部分都需要配置,根据需求而定
1、mode:环境模式
1)development:开发环境,打包时代码不压缩,默认开启调试,
2)production:生产环境,即打包要发布到线上的代码,默认开启代码压缩、混淆代码,不开启代码调试
mode:'development'
2、entry:入口配置,分单、多入口,(即要编译的文件,webpack以js文件为入口文件)。
1)单入口:
entry:'./src/js/index.js’ //打包出index.bundle.js文件
entry:['./src/js/index.js', './src/js/app.js’] //这两个文件打包时合并成一个文件index.bundle.js
2)多入口:多入口包含了单入口的写法,推荐使用多入口写法。
entry: {
index: './src/js/index.js',
app: ['./src/js/index.js', './src/js/app.js']
},
//打包出index.bundle.js和app.bundle.js
3、output:输出配置,配置打包后的文件名称及存放路径
output:{
path:path.join(__dirname,’dist’),//输出的目录,与webpack.config.js对比,如不生成在当前目录,输出目录需给全路径
filename:'js/[name].bundle.js',打包后文件放置的目录及文件名称
},
PS:1)、使用path方法,故需在module.exports外部引入path,
const path=require(‘path’),直接引入即可,无需安装,如下图
2)、——dirname为node对象,意思为当前目录下
3)、[name]指向entry中的key值,如index、app
4、module:配置依赖,需使用什么依赖来编译需要打包的文件
如何使用css样式文件:在对应的脚本中使用import引入即可,如上图
module:{
rules:[
//js配置
//css配置有两种
第一种:是将css样式用style标签插入页面(大多数推荐用法)
第二种:是将css样式用link标签插入页面(较少用,是因为入口文件引入几个css就会创建几个link标签,会造成多个ling请求)
//sass配置
//图片配置
//字体文件配置
//html中引入图片配置(webpack4会自动匹配打包后的图片路径,也就是打包后的页面中引入的图片路径是正确的)
]
}
5、plugins(插件)配置
plugins:[
//生成html页面插件:html-webpack-plugin
//需装该插件,后引入如图
//如需生成多个html页面,则new HtmlWebpackPlugin()多个
//如使用jade/pug等html模版,则需要安装对应的loader,并在module.rules新增解析规则
new HtmlWebpackPlugin({
//以下说明几个常用参数,其余参数可搜索html-webpack-plugin查看,也可不用配置参数
template:'./src/html/index.html’,//要生成html文件的原文件
chunks: ['index' //需要插入该html的js文件,从入口文件中选取对应的js文件名称(打包后的js文件名称)
filename:'index.html’,输出的名字
minify:false,//压缩选项,可选object|false,默认false,object对象的参数配置查看html-minifier
})
//清除打包后的文件插件:clean-webpack-plugin
//需装该插件,引入方式如图
new CleanWebpackPlugin(['dist’]),
//静态资源的拷贝,用到copy-webpack-plugin插件
new CopyWebpackPlugin([{
from:path.join(__dirname,’./statics’),
to:’./statics’,
//如本例,将会降静态资源拷贝到dist下的statics
}])
]
6、热加载(实现js、css的自动更新)
1)、使用webpack-de-server插件结合webpack自带的NamedModulesPlugin、HotModuleReplacementPlugin实现热更新,如下
/*
*需安装webpack-de-server、css-hot-loader(用于热更新css)插件
*package.json文件需新增启动命令(命令的key值可以任意取,本例以server为例),如上图
*使用热更新,不会打包出文件,而是存储在内存中
*webpack不会热更新页面(.html/.jade之类)文件,因为其入口文件是js文件,本人在学习中找到一种自动刷新页面的方法,下方说明
配置修改如下
module:{
rules:[
]
}
plugins:[
//页面自动刷新方法
reloadHtml()
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
//开启模块更新的详细进度,在控制台或终端可见,如不需要,可不必配置
]
devServer:{
port:9001,//监听的端口
hot:true,//是否开启热更新
Open:true,//是否打开浏览器
hotOnly:true,//开启模块热更新,而不是页面刷新,同步在对应的脚本需编写依据模块热更新的判断,如下图,如不开启该参数,则为页面刷新,而非热更新
contentBase: path.join(__dirname, "dist”),//监听的目录
watchContentBase: true,
//页面自动刷新新增参数
before(app, server) {
devServer = server;
}
}
更多的参数配置,请查阅官网的配置部分
//页面自动刷新方法,该方法需卸载module.exports外,并将该方法加入plugins,同时devServer中新增before参数,
function reloadHtml() {
this.plugin('compilation',
thing => thing.plugin('html-webpack-plugin-after-emit', trigger));
const cache = {};
function trigger(data, callback) {
const orig = cache[data.outputName];
const html = data.html.source();
// plugin seems to emit on any unrelated change?
if (orig && orig !== html)
devServer.sockWrite(devServer.sockets, 'content-changed');
cache[data.outputName] = html;
callback();
}
}
module.hot.accept(path,callback),可接受两个参数,也可不接受直接调用
1)、path:import中from后的路径,如’./utils’;
2)、callback:回调函数;
模块热更新副作用如下图:
关于module.hot.accept()更多信息网上百度
2)、devServer.proxy代理远程接口请求(可解决跨域问题),例:
入口文件index.js
请求的完整路径为url='https://m.weibo.cn/detail/4248982941508369#comment'
webpack.config.js配置如下
devServer:{
proxy:{
'/detail':{
target:'https://m.weibo.cn’,//指向的域名
changeOrigin:true,//代理服务器的源,需开启该参数,否则请求时会报500
}
}
}
'/detail'这个路径取至完整路径url中的’/detail’,如还想在指向下一层,则配置文件需使用pathRewrite参数,如下配置:
假设url='https://m.weibo.cn/detail/comments/4248982941508369#comment'
devServer:{
proxy:{
'/':{
target:'https://m.weibo.cn’,
changeOrigin:true,
pathRewrite:{
'^/comments':'./detail/comments'
}
}
}
}
入口文件index.js的请求路径修改为,如下图
关于proxy更多参数的配置,请查看http-proxy-middleware插件github
7、第三方JS库的引入,以下讲述种种不同引入库的方法
方法一、使用npm包安装的库,如npm I jquery
在插件配置中新增一个webpack自带的插件
Plugins:[
//使用以下$、jquery即可全局使用jq库
//需引入webpack,如图
//Provide中的P必须为大写,否则会报错
new webpack.ProvidePlugin({
$:’jquery’,
jquery:’jquery',
})
]
方法二:自定义目录的第三方库,如下图src/js/jquery:
1)、在module.exports里新增resolve对象来解析路径
module.exports={
resolve:{
alias:{
jquery:path.resolve(__dirname,'src/js/jquery.js'),
}
}
}
2)、加上方法一的配置即可使用
方法三、使用imports-loader引入
在module下的rules新增规则
module:{
rules:[
{//需装imports-loader
test:path.join(__dirname,’src/js/index.js’),//明确指定那个js文件
use:[
loader:’imports-loader’,
options:{
$:’jquery'
}
]
}
]
}
//第三方库如在自定义目录下,仍就需要解析路径,详情见方法二中的1)步骤
PS:以上配置为基础配置,可打包文件,但是并没有优化打包文件。
五、进阶配置
进阶配置主要为讲述css提取、js公共代码提取、js/css优化(官方叫tree-shaking,即剔除js没有用到的方法及页面没有用到的样式)
1、css提取
PS:提取css的插件由extract-text-webpack-plugin转为mini-css-extract-plugin
引入该插件
module的css需修改,如下:
module:{
rules:[
]
}
plugins配置如下:
plugins:[
new MiniCssExtractPlugin({
filename:’css/[name].min.css’,
//入口文件中引入的css打包后最终只合成一个css
})
]
2、js公共代码提取(针对多入口文件)
例:index.js、app.js都引入了jquery和utils(自己写的功能)
并且在生成页面的chunks中需引入公共代码的chunk名称,特别是manifest模块(webpack自身的脚本),如不引入,所有的脚本将不执行
以下说明常用参数配置,更多参数配置可查阅官网
optimization:{
//压缩混淆js代码配置,需装uglifyjs-webpack-plugin插件,同步引入,如上图
minimize: true,
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: true
}),
//压缩css代码,需装optimize-css-assets-webpack-plugin插件,同步引入,如上图
new OptimizeCSSAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require('cssnano'),
cssProcessorOptions: { discardComments: { removeAll: true } },
canPrint: true
})
],
splitChunks:{
cacheGroups:{
utils:{
name:utils//打包后文件的名称
minSize:30000,//表示文件大于等于30kb时才包
minChunks:2,//表示该文件至少被引用两次才会打包
priority:1,值越大,优先级越高
}
}
}
}
3、css Tree shaking(css代码优化)
方法一:
需装glob-all、purifycss-webpack、purify-css插件
glob-all为解析多路径插件
后在配置文件引入,如下
plugins配置如下:
plugins:[
new purifyCss({
paths:glob.sync([
path.join(__dirname,'public/app.html'),
//可指定具体文件,也可指定所有,如*.html
path.join(__dirname,'app/*.js'),
])
}),
]
PS:如存在提取css配置,则css tree-shaking 创建new的实例必须在提取css的下方,否则无法优化css代码,如下图
4、js tree-shaking(js代码优化)
PS:
1)、js tree-shaking只在生产环境下有效,即mode:’production’,开发环境下无法tree-shaking。
2)、Tree Shaking依赖静态的ES6模块化语法即通过import和export导入导出的代码,如不是,则需要借助第三方插件,但有些情况,仍旧无法tree-shaking
module:{
rules:[
]
}
(完)