⼀、webpack 简介
1.1 webpack
是什么
webpack
是⼀种前端资源构建⼯具,⼀个静态模块打包器(module bundler)。
在 webpack
看来, 前端的所有资源⽂件(js/json/css/img/less/…)都会作为模块处理。
它将根据模块的依赖关系进⾏静态分析,打包⽣成对应的静态资源(bundle)。
官⽹:https://webpack.js.org/
- 前端资源构建⼯具:主要理解⼀下这个前端资源是哪些资源。这些前端资源就是浏览器不认识的
web
资源, ⽐如sass
、less
、ts
,包括js
⾥的⾼级语法。这些资源要能够在浏览器中正常⼯作,必须⼀⼀经过编译处理。⽽webpack
就是可以集成这些编译⼯具的⼀个总的构建⼯具。 - 静态模块打包器:静态模块就是
web
开发过程中的各种资源⽂件,webpack
根据引⽤关系,构建⼀个依赖关系图,然后利⽤这个关系图将所有静态模块打包成⼀个或多个bundle
输出。
1.2 为什么我们需要 webpack
web
开发时调⽤后端接⼝跨域,需要其他⼯具代理或者其他⽅式规避。- 改动代码后要⼿动刷新浏览器,如果做了缓存还需要清缓存刷新。
- 因为
js
和css
的兼容性问题,很多新语法学习了却不能使⽤,⽆论是开发效率和个⼈成⻓都受影响。 - 打包问题。需要使⽤额外的平台如
jekins
打包,⾃⼰编写打包脚本,对各个环节如压缩图⽚,打包js
、打包css
都要⼀⼀处理。
1.3 webpack 五个核⼼概念
1.3.1 Entry
⼊⼝(Entry
)指示 webpack
以哪个⽂件为⼊⼝起点开始打包,分析构建内部依赖图。
// string⽅式: 单⼊⼝,打包形成⼀个trunk,输出⼀个buldle⽂件。trunk的名称默认是main.js
entry: "./src/index.js"
// array⽅式:多⼊⼝,所有⼊⼝⽂件最终只会形成⼀个trunk,输出出去只有⼀个bundle⽂件
entry: ["./src/index.js", "./src/test.js"]
// object:多⼊⼝,有⼏个⼊⼝⽂件就形成⼏个trunk,输出⼏个bundle⽂件。此时trunk的名称就是对象key值
entry: {
index: "./src/index.js",
test: "./src/test.js",
}
//当构建项⽬包含多个⼦项⽬时,每次增加⼀个⼦系统都需要将⼊⼝⽂件写⼊webpack配置⽂件中,其实我们让webpack动态获取⼊⼝⽂件,
// 使⽤ glob 等⼯具使⽤若⼲通配符,运⾏时获得 entry 的条⽬
entry: glob.sync('./project/**/index.js').reduce((acc, path) => {
const entry = path.replace('/index.js', '')
acc[entry] = path
return acc
}, {})
//则会将所有匹配`./project/**/index.js`的⽂件作为⼊⼝⽂件进⾏打包,如果你想要增加⼀个⼦项⽬,仅仅需要在`project`创建⼀个⼦项⽬⽬录,并创建⼀个`index.js` 作为⼊⼝⽂件即可。
//这种⽅式⽐较适合⼊⼝⽂件不集中且较多的场景。
1.3.2 Output
输出(Output
)指示 webpack
打包后的资源 bundles
输出到哪⾥去,以及如何命名。
output: {
// 输出⽂件⽬录(将来所有资源输出的公共⽬录,包括css和静态⽂件等等)
path: path.resolve(__dirname, "dist"), //默认
// ⽂件名称(指定名称+⽬录)
filename: "[name].js", // 默认
// 或使⽤函数返回名(不常⽤)
// filename: (chunkData) => {
// return chunkData.chunk.name === 'main' ? '[name].js': '[name]/[name].js';
// },
// 所有资源引⼊公共路径前缀,⼀般⽤于⽣产环境,⼩⼼使⽤
// 打包⽣成的 index.html ⽂件⾥⾯引⽤资源的前缀
// 也为发布到线上资源的 URL 前缀
// 使⽤的是相对路径,默认为 ''
publicPath: "",
/*
⾮⼊⼝⽂件chunk的名称。所谓⾮⼊⼝即import动态导⼊形成的trunk或者optimization中的splitChunks提取的公共trunk
它⽀持和 filename ⼀致的内置变量
*/
chunkFilename: "[contenthash:10].chunk.js",
/* 当⽤ Webpack 去构建⼀个可以被其他模块导⼊使⽤的库时需要⽤到library */
library: {
name: "[name]",//整个库向外暴露的变量名
type: "window"//库暴露的⽅式
}
},
1.3.3 Loader
Loader
让webpack
能够去处理那些⾮JavaScript
⽂件 (webpack
⾃身只理解JavaScript
)
rules: [
{
// 匹配哪些⽂件
test: /\.css$/,
// 使⽤哪些loader进⾏处理。执⾏顺序,从右⾄左,从下⾄上
use: [
// 创建style标签,将js中的样式资源(就是css-loader转化成的字符串)拿过来,添加到⻚⾯head标签⽣效
"style-loader",
// 将css⽂件变成commonjs⼀个模块加载到js中,⾥⾯的内容是样式字符串
"css-loader",
{
// css 兼容处理 postcss,注意需要在package.json配置browserslist
loader: "postcss-loader",
options: {
postcssOptions: {
ident: "postcss",
// postcss-preset-env插件:帮postcss找到package.json中的browserslist配置,根据配置加载指定的兼容性样式
plugins: [require("postcss-preset-env")()],
},
},
}],
},
{
test: /\.js$/,
// 注意需要在package.json配置browserslist,否则babel-loader不⽣效
// js兼容处理 babel
loader: "babel-loader", // 规则只使⽤⼀个loader时推荐写法
options: {
presets: [
[
"@babel/preset-env",// 预设:指示babel做怎么样的兼容处理
{
useBuiltIns: "usage", //按需加载
corejs: {
version: "3",
},
targets: "defaults",
}
]
]
}
},
/**
* Webpack5.0新增资源模块(asset module),它是⼀种模块类型,允许使⽤资源⽂件(字体,图标等)⽽⽆需配置额外loader。⽀持以下四个配置
* asset/resource 发送⼀个单独的⽂件并导出 URL。之前通过使⽤ file-loader 实现。
* asset/inline 导出⼀个资源的 data URI。之前通过使⽤ url-loader 实现。
* asset/source 导出资源的源代码。之前通过使⽤ raw-loader 实现。
* asset 在导出⼀个 data URI 和发送⼀个单独的⽂件之间⾃动选择。之前通过使⽤ url-loader,并且配置资源体积限制实现。
**/
// Webpack4使⽤file-loader实现
{
test: /\.(eot|svg|ttf|woff|)$/,
type: "asset/resource",
generator: {
// 输出⽂件位置以及⽂件名
filename: "fonts/[name][ext]"
},
},
// Webpack4使⽤url-loader实现
{
//处理图⽚资源
test: /\.(jpg|png|gif|)$/,
type: "asset",
generator: {
// 输出⽂件位置以及⽂件名
filename: "images/[name][ext]"
},
parser: {
dataUrlCondition: {
maxSize: 10 * 1024 //超过10kb不转base64
}
}
},
]
1.3.4 Plugins
插件(Plugins
)可以⽤于执⾏范围更⼴的任务。插件的范围包括,从打包优化和压缩,⼀直到重新定义环境中的变量等。
它并不会影响 Webpack
的核⼼⼯作过程,只是 Webpack
为了提供⼀个强⼤的扩展能⼒,它为整个⼯作过程的每个环节都预制了⼀个钩⼦,也就是说我们可以通过插件往 Webpack
⼯作过程的任意环节植⼊⼀些⾃定义的任务,从⽽扩展 Webpack
打包功能以外的能⼒。
// CleanWebpackPlugin帮助你在打包时⾃动清除dist⽂件,学习时使⽤⽐较⽅便
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
// HtmlWebpackPlugin帮助你创建html⽂件,并⾃动引⼊打包输出的bundles⽂件。⽀持html压缩。
const HtmlWebpackPlugin = require("html-webpack-plugin");
// 该插件将CSS提取到单独的⽂件中。它会为每个trunk创造⼀个css⽂件。需配合loader⼀起使⽤
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// 该插件将在Webpack构建过程中搜索CSS资源,并优化\最⼩化CSS
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
// vue-loader V15版本以上,需要引⼊VueLoaderPlugin插件,它的作⽤是将你定义过的js、css等规则应⽤到vue⽂件中去。
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
module: {
rules: [{
test: /\.vue$/,
loader: "vue-loader"
},
{
test: /\.css$/,
use: [
// MiniCssExtractPlugin.loader的作⽤就是把css-loader处理好的样式资源(js⽂件内),单独提取出来 成为css样式⽂件
MiniCssExtractPlugin.loader,//⽣产环境下使⽤,开发环境还是推荐使⽤style-loader
"css-loader",
],
}],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template:"index.html"
}),
new MiniCssExtractPlugin({
filename: "css/built.css",
}),
new OptimizeCssAssetsWebpackPlugin(),
new VueLoaderPlugin(),
]
}
插件都是通过往 Webpack ⽣命周期的钩⼦中挂载任务函数实现的。
class RemoveCommentsPlugin {
apply(compiler) {
compiler.hooks.emit.tap('RemoveCommentsPlugin', compilation => {
// compilation => 可以理解为此次打包的上下⽂
for (const name in compilation.assets) {
if (name.endsWith('.js')) {
const contents = compilation.assets[name].source()
const noComments = contents.replace(/\/\*{2,}\/\s?/g, '')
compilation.assets[name] = {
source: () => noComments,
size: () => noComments.length
}
}
}
})
}
}
1.3.5 Mode
模式(Mode
)指示 webpack
使⽤相应模式的配置。
选项 | 描述 | 特点 |
---|---|---|
development | 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development。启⽤ NamedChunksPlugin 和 NamedModulesPlugin。 | 能让代码本地调试,运⾏的环境 |
production | 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。启⽤FlagDependencyUsagePlugin,FlagIncludedChunksPlugin,ModuleConcatenationPlugin,NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 TerserPlugin。 | 能让代码优化上线运⾏的环境 |
⼆、webpack 的使⽤
Webpack 在整个打包的过程中:
通过 Loader 处理特殊类型资源的加载,例如加载样式、图⽚;
通过 Plugin 实现各种⾃动化的构建任务,例如⾃动压缩、⾃动发布。
- Webpack CLI 启动打包流程;
- 载⼊ Webpack 核⼼模块,创建 Compiler 对象;
- 使⽤ Compiler 对象开始编译整个项⽬;
- 从⼊⼝⽂件开始,解析模块依赖,形成依赖关系树;
- 递归依赖树,将每个模块交给对应的 Loader 处理;
- 合并 Loader 处理完的结果,将打包结果输出到 dist ⽬录。
先安装 webpack 相关的 npm 包,然后使⽤ webpack-cli 所提供的命令⾏⼯具进⾏打包。
2.1 初始化配置
2.1.1 初始化 package.json
npm init
2.1.2 下载并安装 webpack
npm install webpack webpack-cli -g
npm install webpack webpack-cli -D
2.2 编译打包应⽤
2.2.1 创建⽂件
选项 描述 特点
development 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development。
启⽤ NamedChunksPlugin 和 NamedModulesPlugin。
能让代码本地调试
运⾏的环境
production
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。
启⽤FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin,
NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 TerserPlugin。
能让代码优化上线运⾏的环境
2.2.2 运⾏指令
开发环境指令:webpack src/index.js -o build/built.js --mode=development
功能:webpack
能够编译打包 js
和 json
⽂件,并且能将 es6
的模块化语法转换成浏览器能识别的语法。
⽣产环境指令:webpack src/index.js -o build/built.js --mode=production
功能:在开发配置功能上多⼀个功能,压缩代码。
2.2.3 结论
webpack
能够编译打包js
和json
⽂件。- 能将
es6
的模块化语法转换成浏览器能识别的语法。 - 能压缩代码。
2.2.4 问题
- 不能编译打包
css
、img
等⽂件。 - 不能将
js
的es6
基本语法转化为es5
以下语法。
三、webpack 开发、⽣产配置
开发环境配置
/*
开发环境配置:能让代码运行
运行项目指令:
webpack 会将打包结果输出出去
npx webpack-dev-server 只会在内存中编译打包,没有输出
*/
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// entry: './src/js/index.js',
entry: resolve(__dirname, './src/js/index.js') ,
//entry: ['./src/js/index.js', './src/index.html'], HMR开启
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
// loader的配置
{
// 处理less资源
// 匹配哪些文件
test: /\.less$/, // 匹配哪些文件
// use数组中loader执行顺序:从右到左,从下到上 依次执行
// style-loader:创建style标签,将js中的样式资源插入进行,添加到head中生效
// css-loader:将css文件变成commonjs模块加载js中,里面内容是样式字符串
// less-loader:将less文件编译成css文件 需要下载 less-loader和less
use: ['style-loader', 'css-loader', 'less-loader']
},
{
// 处理css资源
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
// 处理图片资源
// 问题:默认处理不了html中img图片
// 处理图片资源
test: /\.(jpg|png|gif)$/,
// 使用一个loader
// 下载 url-loader file-loader
loader: 'url-loader',
options: {
// 图片大小小于8kb,就会被base64处理
// 优点: 减少请求数量(减轻服务器压力)
// 缺点:图片体积会更大(文件请求速度更慢)
limit: 8 * 1024,
// 给图片进行重命名
// [hash:10]取图片的hash的前10位
// [ext]取文件原来扩展名
name: '[hash:10].[ext]',
// 关闭es6模块化
// 问题:因为url-loader默认使用es6模块化解析,而html-loader引入图片是commonjs
// 解析时会出问题:[object Module]
// 解决:关闭url-loader的es6模块化,使用commonjs解析
esModule: false,
outputPath: 'imgs'
}
},
{
// 处理html中img资源
// 处理html文件的img图片(负责引入img,从而能被url-loader进行处理)
test: /\.html$/,
loader: 'html-loader'
},
// 打包其他资源(除了html/js/css资源以外的资源)
{
// 处理其他资源
exclude: /\.(html|js|css|less|jpg|png|gif)/,
loader: 'file-loader',
options: {
name: '[hash:10].[ext]',
outputPath: 'font'
}
}
]
},
plugins: [
// plugins的配置
// html-webpack-plugin
// 功能:默认会创建一个空的HTML,自动引入打包输出的所有资源(JS/CSS)
// 需求:需要有结构的HTML文件
new HtmlWebpackPlugin({
// 复制 './src/index.html' 文件,并自动引入打包输出的所有资源(JS/CSS)
template: './src/index.html'
})
],
mode: 'development',
// 开发服务器 devServer:用来自动化(自动编译,自动打开浏览器,自动刷新浏览器~~)
// 特点:只会在内存中编译打包,不会有任何输出
// 启动devServer指令为:npx webpack-dev-server
devServer: {
// 运行代码的目录
contentBase: resolve(__dirname, 'build'),
// 监视 contentBase 目录下的所有文件,一旦文件变化就会 reload
watchContentBase: true,
watchOptions: {
// 忽略文件
ignored: /node_modules/
},
// 启动gzip压缩
compress: true,
// 端口号
port: 5000,
// 域名
host: 'localhost',
// 自动打开浏览器
open: true,
// 开启HMR功能
/*
HMR: hot module replacement 热模块替换 / 模块热替换
作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块)
极大提升构建速度
样式文件:可以使用HMR功能:因为style-loader内部实现了~
js文件:默认不能使用HMR功能 --> 需要修改js代码,添加支持HMR功能的代码
注意:HMR功能对js的处理,只能处理非入口js文件的其他文件。
html文件: 默认不能使用HMR功能.同时会导致问题:html文件不能热更新了~ (不用做HMR功能)
解决:修改entry入口,将html文件引入
*/
// 当修改了webpack配置,新配置要想生效,必须重新webpack服务
hot: true,
// 不要显示启动服务器日志信息
clientLogLevel: 'none',
// 除了一些基本启动信息以外,其他内容都不要显示
quiet: true,
// 如果出错了,不要全屏提示~
overlay: false,
// 服务器代理 --> 解决开发环境跨域问题
proxy: {
// 一旦devServer(5000)服务器接受到 /api/xxx 的请求,就会把请求转发到另外一个服务器(3000)
'/api': {
target: 'http://localhost:3000',
// 发送请求时,请求路径重写:将 /api/xxx --> /xxx (去掉/api)
pathRewrite: {
'^/api': ''
}
}
}
},
devtool: 'eval-source-map',
resolve: {
// 配置解析模块路径别名: 优点简写路径 缺点路径没有提示
alias: {
$css: resolve(__dirname, 'src/css')
},
// 配置省略文件路径的后缀名
extensions: ['.js', '.json', '.jsx', '.css'],
// 告诉 webpack 解析模块是去找哪个目录
modules: [resolve(__dirname, '../../node_modules'), 'node_modules']
}
};
生产环境配置
const { resolve } = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
// 定义nodejs环境变量:决定使用browserslist的哪个环境
process.env.NODE_ENV = "production";
// 复用loader
const commonCssLoader = [
// 创建style标签,将样式放入
// 'style-loader',
// 这个loader取代style-loader。作用:提取js中的css成单独文件
MiniCssExtractPlugin.loader,
"css-loader",
{
// 还需要在package.json中定义browserslist
/*
css兼容性处理:postcss --> postcss-loader postcss-preset-env
帮postcss找到package.json中browserslist里面的配置,通过配置加载指定的css兼容性样式
"browserslist": {
// 开发环境 --> 设置node环境变量:process.env.NODE_ENV = development
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
// 生产环境:默认是看生产环境
"production": [
">0.2%",
"not dead",
"not op_mini all"
]
}
*/
// 使用loader的默认配置
// 'postcss-loader',
// 修改loader的配置
loader: "postcss-loader",
options: {
ident: "postcss",
plugins: () => [require("postcss-preset-env")()],
},
},
];
module.exports = {
entry: "./src/js/index.js",
output: {
filename: "js/built.js",
path: resolve(__dirname, "build"),
},
module: {
rules: [
{
test: /\.css$/,
use: [...commonCssLoader],
},
{
test: /\.less$/,
use: [...commonCssLoader, "less-loader"],
},
/*
正常来讲,一个文件只能被一个loader处理。
当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序:
先执行eslint 在执行babel
*/
{
// 在package.json中eslintConfig --> airbnb
test: /\.js$/,
exclude: /node_modules/,
// 优先执行
enforce: "pre",
loader: "eslint-loader",
options: {
// 自动修复eslint的错误
fix: true,
},
},
/*
js兼容性处理:babel-loader @babel/core
1. 基本js兼容性处理 --> @babel/preset-env
问题:只能转换基本语法,如promise高级语法不能转换
2. 全部js兼容性处理 --> @babel/polyfill
问题:我只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了~
3. 需要做兼容性处理的就做:按需加载 --> core-js
*/
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
options: {
// 预设:指示babel做怎么样的兼容性处理
presets: [
[
"@babel/preset-env",
{
// 按需加载
useBuiltIns: "usage",
// 指定core-js版本
corejs: { version: 3 },
// 指定兼容性做到哪个版本浏览器
targets: {
chrome: "60",
firefox: "50",
ie: "9",
safari: "10",
edge: "17"
},
},
],
],
cacheDirectory: true //bable 缓存
},
},
{
test: /\.(jpg|png|gif)/,
loader: "url-loader",
options: {
limit: 8 * 1024,
name: "[hash:10].[ext]",
outputPath: "imgs",
esModule: false,
},
},
{
test: /\.html$/,
loader: "html-loader",
},
{
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: "file-loader",
options: {
outputPath: "font",
},
},
],
},
plugins: [
// 对输出的css文件进行重命名
new MiniCssExtractPlugin({
filename: "css/built.css",
}),
// 压缩css
new OptimizeCssAssetsWebpackPlugin(),
// 压缩html代码
new HtmlWebpackPlugin({
template: "./src/index.html",
minify: {
// 移除空格
collapseWhitespace: true,
// 移除注释
removeComments: true,
},
}),
],
// 生产环境下会自动压缩js代码
mode: "production",
externals: {
// 拒绝jQuery被打包进来
jquery: 'jQuery'
}
};
四、webpack 性能优化
4.1 开发环境性能优化
- 优化打包构建速度
- HMR
- 优化代码调试
- source-map : ⼀种 提供源代码到构建后代码映射 技术 (如果构建后代码出错了,通过映射可以追踪源代码错误)[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
- a.source-map:外部
产⽣⼀个单独的source-map⽂件,功能最完全,但会减慢打包速度 - b. inline-source-map:内联
只⽣成⼀个内联source-map
错误代码准确信息 和 源代码的错误位置 - c. hidden-source-map:外部
错误代码错误原因,但是没有错误位置
不能追踪源代码错误,只能提示到构建后代码的错误位置 - d.eval-source-map:内联
使⽤eval打包源⽂件模块,直接在源⽂件中写⼊⼲净完整的source-map,不影响构建速度,但影响执⾏速度和安
全,建议开发环境中使⽤,⽣产阶段不要使⽤ - e.nosources-source-map:外部
错误代码准确信息, 但是没有任何源代码信息 - f.cheap-source-map:外部
错误代码准确信息 和 源代码的错误位置,只能精确的⾏ - g.cheap-module-source-map:外部
错误代码准确信息 和 源代码的错误位置
module会将loader的source map加⼊
- a.source-map:外部
- source-map : ⼀种 提供源代码到构建后代码映射 技术 (如果构建后代码出错了,通过映射可以追踪源代码错误)[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
内联 和 外部的区别:1. 外部⽣成了⽂件,内联没有 2. 内联构建速度更快
开发环境推荐使⽤:
- 1.eval :每个模块使⽤eval()和//@ sourceURL执⾏。这是⾮常快。主要缺点是,它没有正确显示⾏号,因为它被映射到转换代码⽽不是原始代码(没有来⾃加载器的源映射)。
- 2.eval-source-map:每个模块使⽤eval()执⾏,⽽SourceMap作为DataUrl添加到eval()中。最初它是缓慢的,但是
它提供快速的重建速度和产⽣真实的⽂件。⾏号被正确映射,因为它被映射到原始代码。它产⽣了最优质的开发资源。 - 3.cheap-eval-source-map:与eval-source-map类似,每个模块都使⽤eval()执⾏。它没有列映射,它只映射⾏
号。它忽略了来⾃加载器的源代码,并且只显示与eval devtool相似的经过转换的代码。 - 4.cheap-module-eval-source-map:类似于cheap-eval-source-map,在本例中,来⾃加载器的源映射被处理以获
得更好的结果。然⽽,加载器源映射被简化为每⼀⾏的单个映射。
⽣产环境推荐使⽤:
- 1.(none) :(省略devtool选项)-不触发SourceMap。这是⼀个很好的选择。
- 2.source-map:⼀个完整的SourceMap是作为⼀个单独的⽂件。它为bundle 添加了引⽤注释,因此开发⼯具知道在哪⾥找到它。
- 3.hidden-source-map:与source-map相同,但不向bundle 添加引⽤注释。如果您只希望SourceMaps从错误报告
中映射错误堆栈跟踪,但不想为浏览器开发⼯具暴露您的SourceMap,可以使⽤此选项。 - 4.nosources-source-map:⼀个SourceMap是在没有源代码的情况下创建的。它可以⽤于在客户机上映射堆栈跟
踪,⽽不暴露所有源代码。您可以将源映射⽂件部署到webserver。
webpack devtool: https://webpack.docschina.org/configuration/devtool/
4.2 ⽣产环境性能优化
- 优化打包构建速度
- oneOf --每个不同类型的⽂件在 loader 转换时,都会被命中,遍历 module 中 rules 中所有 loader.
- 使⽤ oneOf 根据⽂件类型加载对应的 loader,只要能匹配⼀个即可退出,
- 对于同⼀类型⽂件,⽐如处理 js,如果需要多个 loader,可以单独抽离 js 处理,确保 oneOf ⾥⾯⼀个⽂件类型对应⼀个 loader
- 可以配置 enforce: ‘pre’,指定优先执⾏
- babel 缓存: cacheDirectory: true --> 让第⼆次打包构建速度更快
- hash: 每次 wepack 构建时会⽣成⼀个唯⼀的 hash 值。
问题: 因为 js 和 css 同时使⽤⼀个 hash 值。–> 如果重新打包,会导致所有缓存失效。(可能我却只改动⼀个⽂件) - chunkhash:根据 chunk ⽣成的 hash 值。如果打包来源于同⼀个 chunk,那么 hash 值就⼀样
问题: js 和 css 的 hash 值还是⼀样的–> 因为 css 是在 js 中被引⼊的,所以同属于⼀个 chunk - contenthash: 根据⽂件的内容⽣成 hash 值。不同⽂件 hash 值⼀定不⼀样–> 让代码上线运⾏缓存更好使⽤
- hash: 每次 wepack 构建时会⽣成⼀个唯⼀的 hash 值。
- 多进程打包
- externals
- dll
- oneOf --每个不同类型的⽂件在 loader 转换时,都会被命中,遍历 module 中 rules 中所有 loader.
- 优化代码运⾏的性能
- 缓存(hash-chunkhash-contenthash)
- tree shaking
- code split
- 懒加载/预加载
- pwa