webpack5是一个打包工具,可以按我们自己的方式对文件或是目录进行处理,生成我们需要的样子,如何更灵活的配置,就要先从基本的开始,然后一点点扩展
项目的目录结构
|-config
|-base
|-config
|-dev
|-pro
|-public
|-favicon.ico
|-index.html
|-node_modules
|-src
|-index.js
|-package.json
1.构建基本项目
初始化package.json
npm init -y
安装webpack相关包
npm i -D webpack-dev-server webpack webpack-cli webpack-merge
webpack,webpack-cli:主要执行webpack打包命令
webpack-dev-server: 开启静态服务
webpack-merge:合并文件
验证:
src/index.js //入口文件
const a = 10;
console.log(a)
config/base.js //所有环境的公用配置
const path = require('path');module.exports = { entry:{ main: './src/index.js' }, output: { publicPath: '/', path: path.resolve(__dirname, '..', 'dist') }}
config/config.js //根据不同的环境执行不同的文件
const { merge } = require('webpack-merge');const baseConfig = require('./base');const devConfig = require('./dev');const proConfig = require('./pro');module.exports = (env, argv) => { let config = argv.mode === 'development' ? devConfig : proConfig; return merge(baseConfig, config);};
config/pro.js //这个文件是打包生产环境的配置
const path = require('path');module.exports = { mode: 'production',};
最后我们需要配置webpack的命令
package.json 中加入如下代码
"scripts": { "build": "webpack --mode=production --config config/config.js" }
那为什么这个是执行命令的呢,我们本地安装的是webpack和wenbpack-cli,webpack是打包工具,而webpack-cli提供了许多命令来使 webpack 的工作变得简单,官方也提供了命令的参数:webpack-cli,大家可以参考着进行配置
上文我们配置好之后,在终端执行npm run build
就可以看到打包成功了,会生成dist目录
1.2.解析babel
如果项目中使用ES6+可以在webpack中进行配置
参考:babel 官网
npm install --save-dev @babel/core @babel/cli @babel/preset-env babel-loader
安装成功后在config/base.js
module: { rules: [ { test: /\.js(\?.*)?$/, exclude: (file) => /node_modules/.test(file) && !/\.js/.test(file), use: { loader: 'babel-loader' } } ] }
此时,就可以正常的编写ES6的代码了,但这个只是解析语法,对于一些类或函数,比如Promise,includes等需要引入一些辅助函数,来解决这个问题
npm i -D @babel/plugin-transform-runtime @babel/runtime-corejs3
在.babelrc中
{ "presets": ["@babel/preset-env"], "plugins": [ [ "@babel/plugin-transform-runtime", { "corejs": 3, "helpers": true, "regenerator": true, "useESModules": false } ] ]}
@babel/preset-env 这个让我们可以使用ES6+的语法,详情参考网上配置
@babel/plugin-transform-runtime 需要搭配corejs 和这个的配置来引入相应的依赖,详情请参考这个地址
配置完成后无效,你可以试一下,那为什么?
因为我们没有配置target,也就是目标浏览器,我们需要再加入如下配置:
.browserslistrc 文件
> 1%
last 2 versions
not ie <= 10
之后就可以正常的打包运行了
1.3.webpack serve配置
其实就是nodeJs写的一个服务器,帮助我们本地开发的部署,以及代理等进行相关的配置
config/dev.js
如下进行了简单的配置
const path = require('path');const webpack = require('webpack');module.exports = { mode: 'development', devtool: 'eval-cheap-module-source-map', devServer: { // 启动devServer,不会在本地生成文件,所有文件会编译在内存中(读取速度快) contentBase: path.join(__dirname, '../dist'), //静态文件根目录 overlay: true, // 错误信息直接显示在浏览器窗口中 port: 8888, publicPath: '/', inline: true, // 实时重载的脚本被插入到你的包(bundle)中,并且构建消息将会出现在浏览器控制台 host: '0.0.0.0', // 设置为0.0.0.0并配合useLocalIp可以局域网访问 useLocalIp: true, // 使用本机IP打开devServer,而不是localhost open: 'chrome',//使用谷歌浏览器打开项目 },};
然后再packge.json中加入
"scripts": { "start": "webpack serve --mode=development --config config/config.js", "build": "webpack --mode=production --config config/config.js" },
启动 npm start
再在config/base.js中加入
plugins:[ new HtmlWebpackPlugin({ template: path.join(__dirname, '../public/index.html'), favicon: path.join(__dirname, '../public/favicon.ico'), //favicon路径 filename: 'index.html', chunks: ['main'], inject: true, minify: true, cache: false, hash: true //开启hash ?[hash] }), ]
可以看到成功运行起来了,
注意:webpack5中,webpack-dev-server 使用webpack serve来启动webpack-dev-server服务器
1.4.热更新
在章节三中,我们似乎加了热更新,但并没有效果,为什么?
我们在src/index.js中加入如下代码,每次更新sum的参数,可以看到控制台并没有打印出相应的值,只有手动刷新值才会变更,为什么呢?
const sum = (a,b) => a+b;console.log(sum(1,2))
在devServer中我们加入了hot: true,而且webpack5在中是不需plugins: [new webpack.HotModuleReplacementPlugin()],,不信加进去也没有效果
后来参考资料说是target的问题就测试了一下:
官方说:tagert告知 webpack 为目标(target)指定一个环境。默认值为 "browserslist"
,如果没有找到 browserslist 的配置,则默认为 "web"
然后我们本地packge.json中加入了“browserslist”,但依然是没有效果的,后来换成了“web”,就可以正常的热更新了
target:"web",
devServer:{ hot: true, //完成HMR
}
JS热更新完成了,但是css呢找官方文档:地址
webpack文档上说需要使用style-loader去使热更新生效,我们试一下
npm install --save-dev style-loader css-loader
注意:如果只使用css-loader是没有效果的
在src/index.js中加入
import "./styles/index.css"
然后再config/base.js中加入如下配置:
{ test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
可以试一下,改变背景色,颜色值也会立即改变
这样样式和JS的热更新就完成了,这个是基本的配置,我么使用这个可以做除了使用Jquery或是其它库来编写代码
1.5.打包
打包很简单
在config/pro中加入如下代码:就可以完成打包了,为什么,因为webpack帮你进行了默认配置
const path = require('path');module.exports = { mode: 'production',};
1.6.清除上次构建的文件
clean-webpack-plugin:
帮助你对每次打包命令执行的时候自动清除dist文件夹,不需要每次手动去删除
在config/pro.js中
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
plugins:[ new CleanWebpackPlugin() ]
这样基本的打包功能就实现了,这个只是初始的模型,后续我们添加一些loader和插件来帮助我们来完善这个功能,下一章节则讲解常用的loader
2.常用Loader
对文件的预处理,按自己的需求将文件加工好后再返回来
2.1 样式处理loader
* style-loader
将模块导出的内容作为样式并添加到 DOM 中
css-loader
加载 CSS 文件并解析 import 的 CSS 文件,最终返回 CSS 代码less-loader
加载并编译 LESS 文件sass-loader
加载并编译 SASS/SCSS 文件postcss-loader
使用 PostCSS 加载并转换 CSS/SSS 文件stylus-loader
加载并编译 Stylus 文件
我们一sass 为例进行配置
先安装如下
npm i -D sass-loader sass dart-sass
在config/base.js中进行配置
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }, { test: /\.scss$/, use: [ 'style-loader', 'css-loader', 'sass-loader' ] }
安装完成后在config/base.js中加入配置,并在styles/index.scss 和styles/index.css 来添加一些样式,如下样式都生效了,说名对scss和css文件的解析成功了
但这个时候文件是在index.html中的style中的,我想将它导出成文件可以使用mini-css-extract-plugin
简单配置:
config/base.js
{ test: /\.css$/, use: [ MiniCssExtractPlugin.loader, 'css-loader' ] }, { test: /\.scss$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader' ] }
plugins:[ new MiniCssExtractPlugin(),
]
打包之后就会多了个main.css文件出来,当前你也可以根据环境来判断具体应该适应style-loader还是MiniCssExtractPlugin.loader,具体请参考我的github
2.2加载资源文件
需要使用file-loader和url-loader
{ test: /\.(|woff|woff2|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, use: [ { loader: 'file-loader', options: { esModule: false, limit: 2048, name: 'assets/fonts/[name].[ext]', publicPath: '/' } } ] }, { test: /\.(png|jpg|gif|svg|ico)$/i, //正则表达式匹配图片规则 use: [ { loader: 'url-loader', options: { esModule: false, limit: 2048, name: 'assets/images/[name].[ext]', //images:图片打包的文件夹; publicPath: '/' } } ] }
这个主要是对图片和字体的处理
这个只是配置的基础,后续会陆续进行扩展,比如如何使用cssmodule ,如何配置多环境,如何配置vue 的eslint以及单元测试配置等