【笔记】Webpack学习笔记

前言

Webpack学习笔记

下载依赖

1
npm install -D webpack webpack-cli

执行打包

  • 如果项目根目录存在webpack.config.js文件,则读取自定义配置,否则使用默认配置

--stats detailed:展示详细打包信息
--watch:观察者模式,实时侦测文件变化并自动重新打包
--env <key>--env <key>=<value>:指定环境变量
-c <file>--config <file>:指定配置文件,缺省值为./webpack.config.js

--entry <file>.js:指定入口文件,缺省值为./src/index.js
--ouput-filename <file_name>.js:指定打包后的文件名,缺省值为main.js
--output-path <dir_name>:指定打包后的文件所在目录,缺省值为./dist

1
webpack

配置文件

mode:打包环境

none:不指定打包环境
development:开发环境
production:生产环境

entry:指定入口文件
output:指定出口配置

filename:指定打包后的文件名
path:指定打包后的文件所在目录,必须是绝对路径
clean:是否清理上一次打包的文件
publicPath:指定打包后的资源的URL前缀

devtool:SourceMap配置,在生产环境下不要生成SourceMap
module:解析文件的模块配置
plugins:插件配置
optimization:代码优化配置
performance:性能配置

webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const path = require("path");

module.exports = {
mode: "none",
entry: "index.js",
output: {
filename: "main.js",
path: path.resolve(__dirname, "dist"),
clean: true,
publicPath: "http://127.0.0.1:80/",
},
devtool: "inline-source-map",
resolve: {},
module: {},
plugins: [],
optimization: {},
performance: {}
}

输出配置

输出为单个JS文件
webpack.config.js
1
2
3
4
5
module.exports = {
output: {
filename: "main.js",
}
}
输出为多个JS文件
webpack.config.js
1
2
3
4
5
6
module.exports = {
output: {
filename: "[name].js",
path: path.resolve(__dirname, "dist"),
}
}

解析器配置

手动指定导入的文件所使用的解析器

  • 通过<loader_name>来解析<file>
1
import "<loader_name>!<file>";

通过配置文件配置解析器

test:使用正则表达式匹配需要解析的文件名
use:指定解析器

"":只有一个解析器,并且无其他配置,则可以直接指定解析器名
["", ""]:有多个解析器,但无其他配置,则可以直接指定多个解析器名,多个解析器调用顺序为从后往前
[{}, {}]:有多个解析器,且有其他配置,则可以指定多个解析器配置,多个解析器调用顺序为从后往前

type:指定资源类型

asset/resource:直接打包文件,并得到文件的URL,通过内置的file-loader实现
asset/inline:得到文件的的Base64编码值,通过内置的url-loader实现
asset/source:得到文件的原始内容,通过内置的raw-loader实现
asset:缺省值,根据parser.dataUrlCondition.maxSize配置的文件大小(单位字节),小于等于则切换为asset/inline,大于则切换为asset/resource

generator:指定打包后的文件配置

filename:指定打包后的文件路径及文件名

[path]:原始文件路径
[name]:原始文件名,不包含扩展名
[hash]:原始文件哈希值(包含文件内容及文件元数据)

[hash:<num>]:截取指定长度的文件哈希值

[contenthash]:原始文件内容哈希值
[ext]:原始文件扩展名
[query]:原始文件查询字符串

webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module.exports = {
module: {
rules: [
{
test: /<file_name>/,
use: "<loader_name>",
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10*1024
}
},
generator: {
filename: "[path][name][hash][contenthash][ext][query]"
},
}
]
}
}

解析规则配置

mainFiles:导入时自动匹配主文件名
extensions:导入时自动匹配扩展名

webpack.config.js
1
2
3
4
5
6
7
8
9
module.exports = {
resolve: {
mainFiles: ["index"]
extensions: [".wasm", ".mjs", ".js", ".json"],
alias: {
"@src": path.resolve(__dirname, "src")
}
}
}
  • 导入时仅指定目录,自动匹配主文件名
1
import "@src/dir"
  • 导入时仅指定文件名,自动匹配扩展名
1
import "@src/file"

插件配置

全局变量插件

修改配置文件
  • 定义全局变量
webpack.config.js
1
2
3
4
5
6
7
8
9
const { DefinePlugin } = require("webpack");

module.exports = {
plugins: [
new DefinePlugin({
"key": JSON.stringify("value")
})
]
}
使用全局变量
1
console.log(key);
内置全局变量
1
console.log(process.env.NODE_ENV);

代码分离

准备多个JS文件

1
2
3
+ src
- index.js
- another.js

方案一:修改入口节点

  • 这种方案在引用公共JS文件时,会重复打包

修改配置文件

entry:指定多个入口节点
output.filename:指定输出文件名

webpack.config.js
1
2
3
4
5
6
7
8
9
module.exports = {
entry: {
index: "./src/index.js",
another: "./src/another.js",
},
output: {
filename: "[name].bundle.js",
}
}

方案二:抽离公共JS文件为trunk

  • 这种方案在引用公共JS文件时,不会重复打包

修改配置文件

  • 公共模块会被打包为shared.bundle.js
webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = {
entry: {
index: {
import: "./src/index.js",
dependOn: "shared",
},
another: {
import: "./src/another.js",
dependOn: "shared",
},
shared: "公共模块名",
},
output: {
filename: "[name].bundle.js",
}
}

方案三:通过插件抽离公共JS文件为chunk

  • 通过内置的插件split-chunks-plugin实现插件抽离公共JS文件为chunk

修改配置文件

webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
entry: {
index: "./src/index.js",
another: "./src/another.js",
},
output: {
filename: "[name].bundle.js",
},
optimization: {
splitChunks: {
chunks: "all",
}
}
}

方案四:动态导入

  • 根据使用import()函数导入的JS文件,作为公共JS文件
  • 动态导入可以和静态导入组合使用
  • 通过动态导入的方式打包的公共JS文件,会自动进行懒加载,只有在被调用的时候,浏览器才会下载对应的JS文件

在JS文件中导入JS文件

another.js
1
2
3
4
5
function getComment() {
return import("公共模块名").then(({公共模块内的函数名}) => {
公共模块内的函数名();
});
}
index.js
1
import "./another.js"
  • 公共JS文件会被打包为目录民_文件名_js.bundle.js文件
通过魔法注释定义公共模块打包后的文件名
  • 魔法注释的多个选项之间用,隔开
another.js
1
2
3
4
5
function getComment() {
return import(/* webpackChunkName: "自定义文件名" */"公共模块名").then(({公共模块内的函数名}) => {
公共模块内的函数名();
});
}
  • 公共JS文件会被打包为自定义文件名.bundle.js文件

懒加载和预加载

懒加载

  • 在访问HTML时,先不加载这个资源,如果这个资源被调用,才会自动加载这个资源
  • 传送门

预获取

  • 打包后的HTML中会引入<link rel="prefetch" as="script" href="">标签
  • 在访问这个HTML时,先不加载这个资源,只有在网络空闲时,才会自动加载这个资源

通过魔法注释定义模块预获取

webpackPrefetch: true:定义模块预获取

another.js
1
2
3
4
5
function getComment() {
return import(/* webpackPrefetch: true */"模块名").then(({模块内的函数名}) => {
模块内的函数名();
});
}

预加载

  • 与懒加载效果类似

通过魔法注释定义模块预加载

webpackPreload: true:定义模块预加载

another.js
1
2
3
4
5
function getComment() {
return import(/* webpackPreload: true */"模块名").then(({模块内的函数名}) => {
模块内的函数名();
});
}

环境变量

修改配置文件

  • 将配置文件中的对象改为函数,以支持环境变量
webpack.config.js
1
2
3
4
5
module.exports = (env) => {
return {
...
}
}

执行打包时指定环境变量

  • 执行打包时指定环境变量,通过环境变量添加了部分配置
1
webpack --env <key>=<value>

利用环境变量来确定打包环境

修改配置文件

  • 如果传递了环境变量production,则以生产环境打包,否则以开发环境打包
webpack.config.js
1
2
3
4
5
module.exports = (env) => {
return {
mode: env.production ? "production" : "development",
}
}

打包时指定环境变量

  • 传递环境变量production
1
webpack --env production

多环境配置

拆分多个配置文件

准备多个配置文件

1
2
3
4
+ config
- webpack.config.dev.js
- webpack.config.prod.js
- index.js

修改配置文件

  • 重新指定打包后的dist目录的路径为上级目录
webpack.config.dev.js
1
2
3
module.exports = {
path: path.resolve(__dirname, "../dist")
}

执行打包时指定配置文件

-c <file>--config <file>:指定配置文件

1
npx webpack --config ./config/webpack.config.dev.js

抽离公共配置文件

准备多个配置文件

1
2
3
4
5
+ config
- webpack.config.common.js
- webpack.config.dev.js
- webpack.config.prod.js
- index.js

修改配置文件

  • 将公共配置抽离到webpack.config.common.js公共配置文件中
webpack.config.dev.js
1
2
3
module.exports = {
path: path.resolve(__dirname, "../dist"),
}
  • 将非公共配置放到其他配置文件中
webpack.config.dev.js
1
2
3
module.exports = {
mode: "development",
}
webpack.config.prod.js
1
2
3
module.exports = {
mode: "production",
}

合并配置文件

准备多个配置文件

1
2
3
4
5
6
+ config
- webpack.config.js
- webpack.config.common.js
- webpack.config.dev.js
- webpack.config.prod.js
- index.js

下载依赖

1
npm install -D webpack-merge

修改配置文件

webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const { merge } = require("webpack-merge");

const commonConfig = require("./webpack.config.common");
const devConfig = require("./webpack.config.dev");
const prodConfig = require("./webpack.config.prod");

module.exports = (env) => {
switch (true) {
case env.development:
return merge(commonConfig, devConfig);
break;
case env.production:
return merge(commonConfig, prodConfig);
break;
default:
return new Error("No matching configuration was found!");
}
}

执行打包时指定环境

1
webpack --config ./config/webpack.config.js --env production

完成

参考文献

哔哩哔哩——微笑专业教前端