1. webpack是什么
官网对webpack的定义是这样的:webpack是一个现在javascript应用程序的静态模块打包工具。自从出现模块化以后,大家可以将原本一坨代码分离到各个模块中,但是这个引发了一个问题,就是js的每个文件都需要去服务器那,这就导致加载速度变得很慢,于是webpack出现了,他可以将所有的小文件打包成为一个或者多个大文件。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图。其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle。
2. 核心概念
webpack具有四个核心的概念,想要入门webpack,就得先了解这四个核心的概念。
2.1 入口(entry)
Entry是webpack的入口起点指示,他指导者webpack应该从哪个模块开始入手,来作为其构件内部依赖图的开始。可以在配置文件webpack.config.js中配置entry属性来指定一个或者多个入口点。
---webpack.config.js---
const path=require('path') //单入口写法
//模块化写法是 node 环境独有的,浏览器原生不支持使用
module.exports={
entry:'./src/index.js'
}
const config = { //多页面应用程序写法
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js'
}
};
module.exports=config;
注:在多页面应用汇总,每当页面跳转时,服务器将会获取一个新的HTML文档。
2.2 出口(output)
Output属性告诉webpack在哪里输出它所创建的bundles,也可指bundles的名称,默认位置为./dist。整个应用结构都会被编译到指定的输出文件夹中去,最基本的属性包括filename(文件名)和path(输出路径)。
---webpack.config.js---
module.exports={
output:{
path:path.resolve(__dirname,'dist'),
filename:'[name].[contenthash].js'
}
}
注:filename设置contenthash,可以在每次文件发生变化时,生成新的js文件。
以上的配置会将输出打包文件放到当前目录下的dist文件夹中。
2.3加载器(loader)
Loader让webpack能够处理不同的文件。loader可以将所有类型的文件转换为webpack能够处理的有效模块,然后利用webpack的打包能力,对他们进行处理。
在webpack中,loader有两个目标:
- 识别出应该被对应的loader进行转换的文件。(使用test属性)
- 转换这些文件,从而使其能够被添加到依赖图中(并最终添加到bundle中)。(使用use属性)
---webpack.config.js---
module.exports={
module:{
rules:[{
test:/\.js$/,
use:{
loader:'babel-loader'
},
exclude:/node_modules/ //排除node_module里面的js文件。
},
{
test:/\.scss$/,
use:[
{loader:'style-loader'},{loader:css-loader},{loader:scss-loader}
]
}
]
}
}
rules属性值是一个数组,每个数组对象表示了不同的匹配规则,test表示匹配不同的文件后缀;use表示匹配到这个文件后调用的loader来处理,如果需要用到多个loader,则用到数组。
loader支持链式传递,loader的处理顺序是从右到左进行调用的。
以处理scss文件为例:scss-loader将.scss文件编译为.css文件,css-loader将.css文件编译为commonJS模块,style-loader将js字符串转化为style标签并插入到页面中。
2.4插件(plugin)
plugin的目的在于解决loader无法实现的其他事,从打包优化和压缩,到重新定义环境变量,功能强大到可以用来处理各种各样的任务。
---webpack.config.js---
module.exports={
plugins:[
new HtmlWebpackPlugin({
title:'hello-webpack',
template:'src/index.html'
})
]
}
插件htmlwebpackplugin的作用是,在每次build完会生动态成对应的html文件,并自动的将loader处理过的文件插入到该html文件中去。
2.5模式(mode)
mode可以通过配置对象的mode属性进行配置,主要值为production或者development。两种模式的区别在于一个是为生产环境编译打包,一个是为了开发环境编译打包。生产环境模式下,webpack会自动对代码进行压缩等优化,省去了配置的麻烦。
通过代码分离,将开发环境与生产环境相同的代码抽离出来放到webpack.config.base.js文件中,然后在引入到各自的版本中,可以减少代码的重复。
package.json文件中配置,当build文件的时候,使用webpack.config.prod.js配置文件,而start使用默认的配置文件,也就是webpack.config.js文件。
3. 在项目中使用webpack
3.1 清理dist文件
由于使用了contenthash,每次build的js文件都不同名,但是新的文件并不会覆盖旧的文件,旧的文件一直存在/dist文件夹中,随着编译次数的增加,这个文件夹会变得越来越大,所以我们需要清理/dist文件夹,确保文件夹干净整洁。
3.1.1 在package.json中设置
"script":{
build:"rimraf dist &&webpack"
}
原理是在build文件前,先清空dist文件夹,然后再生成新的文件。
注:window系统使用rimraf dist,如果使用bash,可以改为 rm -rf dist
3.1.2 使用插件完成
这里需要用到的插件是:clean-webpack-plugin
---webpack.config.js---
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
plugins: [
new CleanWebpackPlugin(['dist'])
]
};
3.2 搭建开发环境
使用过http-server进行开发时,我们可以打开一个服务器进行实时的预览,虽然http-server也可以用在这里,但是webpack-dev-server提供的预览功能更加强大,而且与webpack结合更紧密。
首先安装依赖:npm i -D webpack webpack-dev-server
---webpack.config.js---
module.exports={
devServer: {
port:8080, //启动服务器端口;
open: false, //启用模块热替换
hot: true, //启用gzip压缩
contentBase: [
path.join(__dirname, "public"), path.join(__dirname, "assets")
]
},
plugins: [
new webpack.HotModuleReplacementPlugin({}) //热更新插件
]
}
---package.json---
"script":{
start:"webpack-dev-server"
}
通过命令行webpack-dev-server来启动服务器,启动后我们发现根目录并没有生成任何文件,因为webpack打包到了内存中,不生成文件的原因在于访问内存中的代码比访问文件中的代码更快。
我们在public/index.html的页面上有时候会引用一些本地的静态文件,直接打开页面的会发现这些静态文件的引用失效了,所以我们devserver中添加了contentBase,指定多个静态资源的目录。
3.3 样式的抽离
我们之前的样式都是通过style-loader插入到页面中去,但是生产环境需要单独抽离样式文件,mini-css-extract-plugin就可以帮我从js中剥离样式,一般是在生产环境中进行样式的抽离。
首先安装依赖:npm i -D mini-css-extract-plugin
---webpack.config.js---
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
//其他配置
module: {
rules: [
{
test: /\.less/,
use: [{
loader: isDev ? 'style-loader' : MiniCssExtractPlugin.loader
},{
loader: 'css-loader'
},{
loader: 'less-loader'
}]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[contenthash].css",
})
]
}
通过使用样式抽离,build会生成.css文件,并在html文件中使用link引入该.css文件。
3.4 使用babel-loader
loader已经在前面讲过如何配置了,但是这里还要拿出来细讲一下,因为这个在项目中非常的重要。babel-loader的作用是将高版本的es语法转换为浏览器能够解析的es5语法。
首先安装依赖:
npm i -D babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime
npm i -S @babel/runtime
---webpack.config.js---
module.exports = {
rules:[{
test:/\.js/,
use:{
loader:{
loader:'babel-loader'
}
},
exclude:/node_modules/
}]
}
把babel的配置提取到根目录,并新建一个.babelrc文件:
---.baberlrc---
{
"presets": [
"@babel/preset-env"
],
"plugins": [
"@babel/plugin-transform-runtime"
]
}