目标
初始化 webpack 项目
配置核心功能
将 ES6+ 转 ES5
处理样式
处理图片等静态资源
创建 html 文件
开发服务器
清除打包文件
多环境打包
第一步:初始化 package.json
npm init -y
第二步:安装 webpack
npm install webpack webpack-cli -D
注意:
第三步:初始化文件和目录
index.js
import name from './name.js'
console.log(name)
name.js
const name = 'shanjian'
export default name
/**
* @description 常用文件夹路径
* @author 山间
*/
const path = require('path')
const srcPath = path.join(__dirname, './', 'src')
const distPath = path.join(__dirname, './', 'dist')
module.exports = {
srcPath,
distPath
}
// webpack.common.js
// 可将开发环境和生产环境下的公用配置抽离到该文件中,可避免重复
const path = require('path')
const { srcPath, distPath } = require('./paths')
module.exports = {
entry: path.join(srcPath, 'index'),
module: {
rules: []
}
}
// webpack.dev.js
const path = require('path')
const webpackCommonConf = require('./webpack.common')
const { merge } = require('webpack-merge')
module.exports = merge(webpackCommonConf, {
mode: 'development'
})
// webpack.prod.js
const path = require('path')
const { srcPath, distPath } = require('./paths')
const webpackCommonConf = require('./webpack.common')
const { merge } = require('webpack-merge')
module.exports = merge(webpackCommonConf, {
mode: 'production',
output: {
path: distPath,
filename: 'main.[contenthash:8].js', // 打包时加上 hash 戳,注意:webpack 5 是 contenthash
}
})
{
// ...
"scripts": {
...
"build": "webpack --config webpack.prod.js"
},
// ...
}
此时,在项目的根目录下输入 npm run build 命令,就可以对项目进行打包了。打包成功后,会在项目根目录下创建一个 dist 文件夹,里面的 main.contenthash.js 就是我们打包后的文件。
由于有些浏览器无法解析 ES6+ 等高级语法,故需要将其转化为浏览器能够解析的低级语法(如:IE浏览器)
第一步:安装依赖 - @babel/core babel-loader @babel/preset-env
npm install @babel/core babel-loader @babel/preset-env -D
第二步:修改 webpack.common.js 配置
module.exports = {
// ...
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader'],
include: srcPath,
exclude: /node_modules/
}
]
}
}
第三步:在根目录添加 .babelrc 文件并配置预置项
// .babelrc
{
"presets": ["@babel/preset-env"],
"plugins": []
}
注意:也可直接在 webpack.common.js 中配置预置项
// webpack.common.js
module.exports = {
// ...
module: {
rules: [
// ES6+ 语法处理
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
}
由于 webpack 默认只能打包处理 commonJS 规范的 js 文件,处理其他类型的文件都需要相对应的处理器进行处理,所以针对 css/less/sass 类型的样式文件,需要引入对应的处理器来处理。
第一步:安装依赖 - style-loader css-loader less less-loader
npm install style-loader css-loader less less-loader -D
第二步:修改 webpack.common.js 配置
// webpack.common.js
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /\.css$/,
use: ['style-loader', 'css-loader'] // 注意 loader 的顺序是从后往前
},
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader']
}
]
}
}
同上,除 js 文件的其他文件使用 webpack 打包,也需要特定的处理器处理,如图片、视频等静态资源
第一步:安装依赖 - url-loader file-loader
npm install url-loader file-loader -D
第二步:注意,这里生产环境和开发环境可以分开配置,为什么这么做?先看配置,后面会解释。
开发环境:
// webpack.dev.js
module.exports = {
// ...
module: {
rules: [
// ...
// 直接产出图片 url
{
test: /\.(png|jpg|jpeg|gif)$/,
use: 'file-loader'
},
// 直接产出视频、音频 url
{
test: /\.(mp4|ogg|mp3|wav)$/,
use: 'file-loader'
}
]
}
}
生产环境:
// webpack.prod.js
module.exports = merge(webpackCommonConf, {
// ...
module: {
rules: [
// ...
// 图片 -- 考虑 base64 编码的情况
{
test: /\.(jpg|jpeg|png|gif)$/,
use: {
loader: 'url-loader',
options: {
// 小于 5kb 的图片用 base64 格式产出
limit: 5 * 1024,
// 否则,依然沿用 file-loader 的形式,产出 url 格式
fallback: {
loader: 'file-loader'
},
// 打包到 /static/video 目录下
outputPath: '/static/img/'
}
}
},
// 视频,跟上面的图片也是一样的道理
{
test: /\.(mp4|ogg|mp3|wav)$/,
use: {
loader: 'url-loader',
options: {
// 小于 5kb 的视频 用 base64 格式产出
limit: 5 * 1024,
// 否则,依然沿用 file-loader 的形式,产出 url 格式
fallback: {
loader: 'file-loader'
},
// 打包到 /static/video 目录下
outputPath: '/static/video/'
}
}
}
]
}
})
为什么?是因为在开发环境下,在本地环境下,不需要把项目打包压缩的特别小,直接引入图片这样打包速度快,利于开发;而在生产环境下,项目越小加载越快,用户体验越好。所以这块针对静态资源的配置可以分别对生产和开发环境进行配置, webpack.common.js 文件里就可以不对静态资源进行处理了。
如何让打包的 js 文件自动地插入到 html 模板中呢?
第一步:安装依赖 - html-webpack-plugin
npm install html-webpack-plugin -D
第二步:修改 webpack.common.js 配置
// ...
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// ...
module: {
// ...
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(srcPath, 'index.html'),
filename: 'index.html',
title: 'Web App'
})
]
}
注意:配置动态网页标题时,需将模板中的
每次打包后都需要手动的点击生成的 index.html 看效果,其实可以直接配置 webpack ,将打包后的文件自动在浏览器打开。这个配置因为是在开发环境下使用,所以可以直接配置在 webpack.dev.js 文件中
第一步:安装依赖 - webpack-dev-server
npm install webpack-dev-server -D
第二步:修改 webpack.dev.js 配置
// webpack.dev.js
module.exports = {
// ...
// 配置 dev-server, 就会帮我们开启自动刷新这个功能
// 自动刷新与热更新的不同:自动刷新保存修改后,整个页
// 面会自动刷新来加载最新的改动,状态会丢失,而热更新
// 是新代码生效,网页不刷新,状态不丢失,有优有劣,酌
// 情使用。
devServer: {
port: 3000, // 默认开启本地服务的端口号
progress: true, // 显示打包的进度条
open: true, // 自动打开浏览器
contentBase: distPath, // 根目录
compress: true, // 启动 gzip 压缩
// 设置代理 —— 如果有需要的话
proxy: {
// 将本地的 /api/xxx 代理到 localhost:3000/api/xxx
'/api': 'http://localhost:3000',
// 将本地的 /api2/xxx 代理到 localhost:3000/xxx
'/api2': {
target: 'http://localhost:3000',
'^api/': ''
}
}
}
}
每次打包如果文件改动的话,都会生成新的打包文件,那之前的文件也就没必要存在了,尤其是在打包文件加了 hash 的情况下,所以我们可以使用此插件帮助我们每次打包前先清除以前的打包文件,即先清空我们的 dist 目录。配置在生产环境下,即 webpack.prod.js
第一步:安装依赖 - clean-webpack-plugin
npm install clean-webpack-plugin -D
第二步:修改 webpack.prod.js 配置
// webpack.prod.js
// ...
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
// ...
plugins: [
new ClearWebpackPlugin() // 会默认清空 output.path 文件夹,即 distPath 文件夹
]
}
因为我们将配置文件抽离成了三个文件,有抽离出来的两个环境下都需要的公共的配置 webpack.common.js ,也有针对开发环境的特殊配置 webpack.dev.js,还有生产环境下的特殊配置 webpack.prod.js ,那我们可以执行不同的命令来达到在生产环境还是开发环境下打包的效果。
第一步:配置 package.json
// ...
"scripts": {
// ...
"dev": "webpack serve --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
},
// ...
第二步:命令行执行对应环境的命令
开发环境运行
npm run dev
生产环境打包运行
npm run build
看到上图,我们创建一个webpack5项目从开发到编译到打包的过程就结束了,也就是我们的普通项目从0到可以开始开发的过程,之后会继续对 webpack 配置的优化进行一个整理和记录,主要有生产环境和开发环境两种不同环境下的优化:
生产环境优化产出代码,使打包出来的产品体积更小,加载依赖更少,加载更快,其中包括 1.如何配置生产环境下的静态资源(本文已经提到了,请翻至【处理图片等静态资源】这一小节),2. 生产环境如何抽离、压缩 css 文件,3. 如何根据功能和配置来拆分模块 splitChunks;等等其他优化手段。
开发环境优化构建速度,可以使本地开发打包编译速度更快,提高开发效率,优化手段主要有:
期待自己能整理出这个系列吧。
本文参考:
从零使用 Webpack5 搭建一个完整的 Vue3 的开发环境 - 掘金
从0创建一个webpack 5项目 - 掘金