我持续组织了近一年的源码共读活动,感兴趣的可以 点此扫码加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列。另外:目前建有江西|湖南|湖北
籍前端群,可加我微信进群。
本文经作者@lin嘟嘟嘟(源码共读群里的小伙伴) 授权转载。
原文链接:https://juejin.cn/post/7062899360995999780 文章较长可收藏
Part11、基础篇
11.1 webpack优点
拥有依赖管理、动态打包、代码分离、按需加载、代码压缩、静态资源压缩、缓存等配置;
webpack 扩展性强,插件机制完善,开发者可自定义插件、loader;
webpack 社区庞大,更新速度快,轮子丰富;
21.2 基础应用
webpack 通过依赖关系图可以获取非代码资源,如 images 或 web 字体等。并会把它们作为依赖提供给应用程序。
每个模块都可以明确表述它自身的依赖,在打包时可根据依赖进行打包,避免打包未使用的模块。
1.2.1 entry(入口)
入口是指依赖关系图的开始,从入口开始寻找依赖,打包构建,webpack 允许一个或多个入口配置;
module.exports = {
entry: './src/index.js'
}
多入口配置:
1.2.2 output(出口)
输出用于配置 webpack 构建打包的出口,如打包的位置,打包的文件名;
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
};
1.2.3 loader(转换)
webpack 自带 JavaScript 和 JSON 文件的打包构建能力,无需格外配置,对于其他类型的文件如css等,则需要安装loader处理;
loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中。
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
};
1.2.4 plugin(插件)
插件则是用于扩展 webpack 的能力;
module.export = {
plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
}
1.2.5 mode(模式)
webpack5 提供了模式选择,包括开发模式、生产模式、空模式,并对不同模式做了对应的内置优化。可通过配置模式让项目性能更优;
module.exports = {
mode: 'development',
};
1.2.6 resolve(解析)
resolve 用于设置模块如何解析,常用配置如下:
alias:配置别名,简化模块引入;
extensions:在引入模块时可不带后缀;
symlinks:用于配置 npm link 是否生效,禁用可提升编译速度。
module.exports = {
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json', '.d.ts'],
alias: {
'@': './',
},
symlinks: false,
}
}
1.2.7 optimization(优化)
optimization 用于自定义 webpack 的内置优化配置,一般用于生产模式提升性能,常用配置项如下:
minimize:是否需要压缩 bundle;
minimizer:配置压缩工具,如 TerserPlugin、OptimizeCSSAssetsPlugin;
splitChunks:拆分 bundle;
runtimeChunk:是否需要将所有生成 chunk 之间共享的运行时文件拆分出来。
module.exports = {
optimization: {
minimizer: [
new CssMinimizerPlugin(),
],
splitChunks: {
chunks: 'all',
// 重复打包问题
cacheGroups:{
vendors:{
//node_modules里的代码
test: /[\\/]node_modules[\\/]/,
chunks: "all",
//chunks name
name: 'vendors',
//优先级
priority: 10,
enforce: true
}
}
},
},
}
31.3 本节代码
本小节需要安装的插件
npm install webpack webpack-cli --save-dev
npm install --save-dev html-webpack-plugin
npm install --save-dev style-loader css-loader
npm install css-minimizer-webpack-plugin --save-dev
代码地址:https://gitee.com/linhexs/webpack5/tree/1.base/[1]
Part22、实践基础篇
42.1 实现目标
分离开发环境、生产环境配置;
模块化开发;
sourceMap 定位警告和错误;
动态生成引入 bundle.js 的 HTML5 文件;
实时编译;
封装编译、打包命令。
52.2 基础配置
2.2.1 新建项目目录
2.2.2 安装插件
npm i webpack-merge -D
npm install webpack webpack-cli --save-dev
2.2.3 添加config目录下的webpack代码
webpack.common.js
// webpack.common.js
module.exports = {} // 暂不添加配置
webpack.dev.js
// webpack.dev.js
const { merge } = require('webpack-merge')
const common = require('./webpack.common')
module.exports = merge(common, {}) // 暂不添加配置
webpack.prod.js
// webpack.prod.js
const { merge } = require('webpack-merge')
const common = require('./webpack.common')
module.exports = merge(common, {}) // 暂不添加配置
2.2.4 entry(入口)
修改 webpack.commom.js:
// webpack.common.js
module.exports = {
// 入口
entry: {
index: './src/index.js',
},
}
2.2.5 output(出口)
output 属性输出它所创建的 bundle的位置和命名;
生产环境的 output 需要通过 contenthash 值来区分版本和变动,可达到清缓存的效果,而本地环境为了构建效率,则不引人 contenthash。
修改webpack.dev.js
// webpack.dev.js
const { merge } = require('webpack-merge')
const common = require('./webpack.common')
const { resolveApp } = require('./paths');
module.exports = merge(common, {
// 输出
output: {
// bundle 文件名称
filename: '[name].bundle.js',
// bundle 文件路径
path: resolveApp('dist'),
// 编译前清除目录
clean: true
},
})
修改webpack.prod.js
// webpack.prod.js
const { merge } = require('webpack-merge')
const common = require('./webpack.common')
const { resolveApp } = require('./paths');
module.exports = merge(common, {
// 输出
output: {
// bundle 文件名称 【只有这里和开发环境不一样】
filename: '[name].[contenthash].bundle.js',
// bundle 文件路径
path: resolveApp('dist'),
// 编译前清除目录
clean: true
}
})
新增 paths.js,封装路径方法resolveApp:
const fs = require('fs')
const path = require('path')
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
module.exports = {
resolveApp
}
占位符作用
[name] - chunk name(例如 [name].js -> app.js)。如果 chunk 没有名称,则会使用其 id 作为名称
[contenthash] - 输出文件内容的 md4-hash(例如 [contenthash].js -> 4ea6ff1de66c537eb9b2.js)
2.2.6 模式(mode)
添加生产环境和开发环境:
module.exports = merge(common, {
// 生产模式
mode: 'production',
})
module.exports = merge(common, {
// 生产模式
mode: 'development',
})
2.2.7 source-map
使用source-map追踪 error 和 warning,将编译后的代码映射回原始源代码;
module.exports = merge(common, {
mode: 'development',
// 开发环境,开启 source map,编译调试
devtool: 'eval-cheap-module-source-map',
})
打包一下试试:
开发:
npx webpack --config config/webpack.dev.js
生产:
npx webpack --config config/webpack.prod.js
2.2.8 HtmlWebpackPlugin
引入 HtmlWebpackPlugin 插件,生成一个 HTML5 文件, 其中包括使用 script 标签的 body 中的所有 webpack 包;
npm install --save-dev html-webpack-plugin
修改webpack.commom.js:
module.exports = {
plugins: [
// 生成html,自动引入所有bundle
new HtmlWebpackPlugin({
title: 'webpack',
}),
],
}
2.2.9 DevServer
webpack-dev-server 提供了一个基本的 web server,并且具有实时重新加载功能;
webpack-dev-server 默认配置 conpress: true,为每个静态文件开启 gzip compression[2];
安装:
npm install --save-dev webpack-dev-server
修改开发环境配置文件webpack.dev.js:
module.exports = merge(common, {
devServer: {
// 告诉服务器位置。
static: {
directory: path.join(__dirname, 'dist'),
},
port: 8888,
hot: true,
},
})
代理配置:
输入命令启动:
npx webpack serve --open --config config/webpack.dev.js
2.2.10 执行命令
通过 cross-env 配置环境变量,区分开发环境和生产环境。
安装:
npm install --save-dev cross-env
修改 package.json:
{
"scripts": {
"dev": "cross-env NODE_ENV=development webpack serve --open --config config/webpack.dev.js",
"build": "cross-env NODE_ENV=production webpack --config config/webpack.prod.js"
},
}
现在可以运行 webpack 指令:
npm run dev:本地构建;
npm run build:生产打包;
62.3 本节代码
代码地址:https://gitee.com/linhexs/webpack5/tree/2.practice/