webpack打包工具基本使用
什么是webpack
我们在进行react、vue2开发的时候,经常会提到工程化,打包工具和webpack啥的,还有项目完成后还要进行打包部署操作啥的。
那么,我就有点疑惑,为啥要打包后进行部署?webpack又是啥?
首先,我们先看一下webpack的官方解释。
At its core, webpack is a static module bundler for modern JavaScript applications.
从本质上讲,webpack 是一个用于现代 JavaScript 应用程序的静态模块打包器 。
所以,webpack就是个打包工具,那么为什么要进行打包,打包这一步骤有什么好处?
首先,我们会发现,webpack经常会出现在工程化项目中,而工程化又是什么?
前面提到过:
工程化:工程化是指将系统化、标准化的方法应用于项目或产品的设计、开发、测试、部署、维护各个环节,强调通过科学的方法和工具来提高效率、保证质量、降低风险。
简单来说:工程化就是运用模块化和组件化开发,有代码规范和质量检测功能,具有自动化流程能力,不必过多考虑配置如何实现,只需要专注于业务逻辑的一种开发方式。
其实webpack就可以帮助我们实现上面的好处,如果是通过脚手架开发的话,一些配置已经默认帮我们配置好了,我们只需要关注业务代码,最后打包后进行部署即可。
又提到打包了,打包是什么呢?
在我看来,打包其实就是工程化开发和原始前端开发的桥梁,我们的工程化项目是不能被浏览器直接所使用的,我们需要将其转化为原始的html、css、js,打包就是代码转化的过程,但在这个过程中,我们可以做一些额外操作,对代码的质量进行提升。比如代码压缩、转化、剪枝等操作,保证兼容性,减少代码体积,提高传输效率等优化。这些操作,对于原始前端开发,都是很困难的,我们每次都需要手动处理、优化、检测、压缩等操作,导致我们在这些步骤上可能会浪费太多时间,而减少了对业务代码的专注,这样开发效率其实是很差的。
官方图片
webpack使用
webpack的使用依赖node环境,我们首先要保证node环境已经安装好。
webpack的使用需要依赖两个包:webpack和webpack-cli。
webpack-cli主要是为了让我们在命令行能使用webpack命令进行打包操作,也是为了配置在package.json中作为脚本命令。
但我们也可以直接使用webpack包,有两种方式:
1 | // 第一种,传递回调函数,查看错误信息或构建成功后的状态信息 |
1 | // 第二种:使用run函数,在run中传递回调函数,查看错误信息或构建成功后的状态信息 |
这样操作起来属实有点麻烦,我还是喜欢通过命令行操作,但前提是要下载webpack-cli包。
然后直接在命令行输入命令npx webpack ./src/test.js回车即可。
我们可以在package.json中添加scripts命令,方便我们使用。
1 | "scripts": { |
注意:配置在package.json中的命令,不需要使用npx,它会自动查找node_modules中.bin中的webpack可执行命令。
前面直接使用webpack包的操作,我们会发现传入了一个配置对象,我们可以通过配置特定信息来改变打包后的产物,如果我们通过使用webpack包的方式,配置起来有些麻烦,但如果我们通过命令行操作的方式,我们只需创建一个配置文件,到时候webpack会自动读取该配置文件进行一些列操作,这个文件名叫webpack.config.js,当然我们也可以通过某种方式改变默认配置文件的指向。
这里展示一个简单的配置文件
1 | const path = require('path'); |
其实webpack.config.js中的配置都是可以通过命令行传入的,而且通过命令行传入参数的优先级比配置文件的高。
比如我们想通过命令行指定输出文件的路径,可以这样写:npx webpack --output-path='./bundle',当然也可以配置在package.json的scripts中。
如果我们不想用这个默认的配置文件,比如我想用wk.config.js,我们只需要在命令行通过config进行指定即可。
1 | webpack --config=wk.config.js |
这么就会根据wk.config.js中的配置进行打包了。
以上我们只说了webpack的打包入口文件、输出文件等这些基本配置,对于打包输出的文件,比如我需要打包的test,js文件内容为const test = 'hello world';console.log(test),生产模式下打包后的文件内容也就是console.log('hello world'),看起来根本没有什么区别,而且打包的也就是js文件,说明webpack默认是支持打包js文件的,但它是否能对代码进行兼容性处理?如果文件时css、html甚至是图片,它又是否支持?如果支持,又是怎么操作的呢?
这就引出了我接下来要说的webpack中的loader和plugin了。
处理css的loader
前面我们提到了,webpack是工程化代码和原始前端开发的桥梁,它可以将工程化代码转化为原始前端开发形式代码,同时它还能进行一些优化操作。
而前面webpack官网的解释又提到:webpack 是一个用于现代 JavaScript 应用程序的静态模块打包器。 而且我们发现在配置webpack时,入口文件一般都是js文件,特别是vue和react的脚手架已经默认指定了入口文件为main.js或index.js。
综上所述,我们可以提取出一些信息:
-
webpack是用于打包js的工具。
-
webpack支持模块化。
-
webpack是现代化开发的工具。
关于现代化开发技术,牵涉到很多,但提到css我们就会想到css预处理器,比如less、sass、stylus等,以及它们的转化和优化工具postcss。
而且我们可以测试一下,如果入口文件为css文件,最终打包结果还是js形式。
所以我们可以总结一下,关于webpack,是支持模块化的,并且可以通过模块化引入css等文件,并对其处理为js数据,最终通过某种方式将该js数据转化为真实的css插入到页面中。
而将css文件转化为js数据,就是loader做的事了,进而可以得出,关于除了js文件外的文件类型,都需要通过loader转化为可被js模块系统识别的形式(如路径、字符串、js对象等)。
这里介绍几个常见的loader。
css-loader
前面我们提到了,wepack默认是支持打包js文件的,但对于css文件,需要使用loader将其转化为可被js模块系统识别的形式,而处理css文件的loader工具,我们可以选择使用css-loader:
1 | npm i css-loader -D |
css-loader的使用
前面我们已经安装了css-loader,目前对于它的使用有两种方式:
-
内联方式。
import 'css-loader![文件路径]'。- 如:
import 'css-loader!../css/index.css'
-
配置方式:在配置文件中进行配置。
上图我们可以发现,css-loader是配置在module配置项中,我们可以知道,module中是用于配置loader的,我们看一下module中的其他配置项:
-
rules:用于配置loader的匹配规则,其值是一个数组,可以填写多个loader规则。 -
test:用于对资源进行匹配,通常会设置成正则表达式。 -
use:其值可以是一个数组,存放UseEntry对象,也是以是一个UseEntry对象,也可以只是一个字符串。- 值是数组时:可以配置多个
UseEntry对象或字符串共同对资源处理。 - 值是一个
UseEntry对象时,表示只使用一个loader处理匹配的资源。 - 值是一个字符串时,表示使用一个loader处理匹配的资源,并且该loader的使用不需要额外配置。
- 值是数组时:可以配置多个
-
UseEntry:描述loader的配置对象,有以下配置:loader:loader的名称,可以是一个字符串,也可以是一个函数。options(可选):loader的配置项,值会被传到laoder中。query:目前已被options替代。
style-loader
经过css-loader的配置后,webpack已经能够正确处理css文件了,但这个时候我们并不能使用css内容,因为这个一步仅仅是将css文件转化为可被js模块系统识别的形式,他并没有被插入到页面中。
这个时候我们就需要使用style-loader了,这个loader可以帮助我们将css内容插入到style标签中,然后插入到页面中。
使用步骤:
(1) 安装style-loader
1 | npm i -D style-loader |
(2) 配置style-loader
webpack中loader的执行顺序是从右到左、从下到上,所以我们需要将style-loader写到css-loader前面,同时由于我们需要css文件进行多个loader处理,所以use项需要是一个数组。
(3) 引入打包后的文件,我们可以发现css样式生效,并在head中插入了style标签。
处理预处理器样式(以Less为例)
在项目开发中,我们通常会选择使用less、sass等css预处理器提高开发效率,但我们前面说的都是针对于css资源的处理,所以我们想使用less这些预处理器,只需要保证能将less转为css即可。
我们有两种方式可以实现less到css的转换:
(1) 通过less命令将less文件转为css文件
1 | # 安装less |
(2) 在webpack中使用less-loader。
1 | npm i less-loader -D |
然后在配置文件中使用即可:
上述是对less文件的操作,如果是sass/scss文件的话,可以用sass-loader这个工具。
postcss-loader
Postcss是一个通过JS转换样式的工具,它可以帮助我们进行一些样式的兼容性处理,比如添加浏览器前缀,压缩样式等。
单独使用postcss
Postcss也可以单独作为一个工具进行使用,操作如下:
(1) 安装postcss-cli
1 | npm i postcss-cli -D |
(2) 编写配置文件postcss.config.js
1 | module.exports = { |
(3) 使用postcss
1 | # npx postcss 目标路径 -o 输出路径 |
在webpack中使用postcss
在webpack中,我们可以用postcss-loader这个工具来使用Postcss。
1 | npm i postcss-loader -D |
注意:postcss需要有对应的插件才能起对应的效果,我们直接使用是没用的。
如果我们想要为样式添加前缀,需要使用autoprefixer插件。
我们需要先对其进行安装:
1 | npm i autoprefixer -D |
接下来就是要让postcss-loader能够使用autoprefixer这个插件了,有两种方式:
(1) 通过UseEntry的options的配置项来配置:
(2) 单独创建postcss配置文件
-
创建
postcss.config.js文件。 -
在
postcss.config.js文件中添加如下内容。
1 | module.exports = { |
使用postcss预设插件
上面我们使用postcss时,如果我们想为样式添加浏览器兼容性前缀,就需要下载一个autoprefixer插件,并且需要在plugins配置项中添加,但我们可能需要用到许多插件,比如说将color()函数转化为兼容性的rgba()函数,我们总不能每一个都安装再配置,一个项目的话可能还好说,但如果多个项目都用到相同的部分了,我们总不能每个项目都再安装一遍。
postcss官方为我们提供了一个postcss-prset-env预设插件,它集成了很多我们常用的插件,我们在开发时,是需要使用它即可,不用再单独配置了,如果有特殊情况的话另说。
(1) 安装postcss-preset-env插件
1 | npm i -D postcss-preset-env |
(2) 配置postcss-preset-env插件
1 | module.exports = { |
在我们配置插件的时候,用一种简写,只需要写字符串即可,postcss会自动在node_modules中寻找对应的插件。
如:
1 | module.exports = { |
webpack打包图片
我们在项目开发中,会使用到图片,我们可能会在css中使用图片,也可能以模块的形式import引入图片,前面我们提到,webpack默认是只对js会进行处理,其他的文件类型需要进行loader转换为webpack的js模块系统能够处理的形式,所以对于图片,我们也需要进行一些特殊处理。
在当前webpack版本(v5.99.9)测试中,在css中使用图片(background: url(./img.png) no-repeat;),是可以直接被以源文件的形式打包的,不需要进行额外的配置。
在webpack5之前,我们处理图片需要用到一些loader:
| loader | 说明 |
|---|---|
| raw-loader | 将文件作为字符串导入 |
| url-loader | 将文件作为数据 URI 内联到捆绑包中 |
| file-loader | 将文件发送到 output 目录 |
在webpack5,我们可以使用Asset Modules类型替换上面这些加载器。
Asset Modules有四种模块类型:
| 模块类型 | 说明 | 适用场景 |
|---|---|---|
| asset/resource | 发送一个单独的文件并导出 URL,之前通过使用 file-loader 实现 |
适用于大文件(如图片、字体) |
| asset/inline | 导出一个资源的 data URI,之前通过使用 url-loader 实现 |
适用于小文件(如图标) |
| asset/source | 导出资源的源代码,之前通过使用 raw-loader 实现 |
适用于文本文件(如 TXT、SVG) |
| asset | 在导出一个 data URI 和发送一个单独的文件之间自动选择,之前通过使用 url-loader,并且配置资源体积限制实现 |
智能选择 resource 或 inline,最常用的通用资源处理方式 |
Asset Module在webpack的配置文件中配置如下:
1 | module: { |
对于图片的默认打包路径,是在output.path指定的目录下,图片名会根据图片的hash值进行重命名,我们也可以手动指定图片的打包路径,有两种方式:
(1) 通过output.assetMoudleFilename配置。
1 | output: { |
(2) 在Asset Module的generator中配置。
1 | module: { |
上面我们看到对于文件的输出路径,我用了[hash]和[ext]这些占位符,通过这些占位符可以动态生成文件名。
这里给出一些占位符的描述:
| 占位符 | 说明 | 示例输入 | 示例输出 |
|---|---|---|---|
[name] |
文件的基本名称(就是源文件名,不包含扩展名) | src/images/logo.png | logo |
[file] |
文件的完整路径,含扩展名 | src/images/logo.png | src/images/logo.png |
[query] |
资源导入时的查询参数(带问号) | src/images/logo.png?size=large | ?size=large |
[fragment] |
片段标识符(带井号) | src/images/logo.png#primary | #primary |
[base] |
文件名(含扩展名) | src/images/logo.png | logo.png |
[ext] |
文件扩展名(带点号) | logo.png | .png |
[hash] |
文件内容哈希值 | 任意文件 | 3c8d8d9e7823e45f |
[path] |
文件相对路径(不含文件名) | src/images/logo.png | src/images/ |
对于[hash]占位符,由于生成的hash值可能太长,不方便查看,所以我们可以使用[hash:count]来指定hash值的长度,如:[hash:4],即只取前4位。
url-loader的limit效果
在我们开发过程中,往往希望小的图片转化为base64,大的图片直接使用,这样可以减少图片的请求,提高性能。
在上述Asset Module的模型类型介绍中,我们可以看出,asset类型可以实现上述效果,而在之前的url-loader中,我们可以设置limit属性,来达到上述效果。
在默认情况下,webpack对于小于8kb的文件,将会视为inline模块类型,否则会被视为resource模块类型,即小于8kb大小的文件,会被转为base64的格式嵌入到文件中,而大于8kb的文件,会发送一个单独的文件,即将源文件复制一份。
但我们也可以自定义文件判断的这个大小,通过Asset Module的配置如下:
1 | { |
在webpack中使用Babel
Babel是一个工具链,主要用于旧浏览器或者环境中将ECMAScript 2015+代码转换为向后兼容的JavaScript代码。
Babel本身可以单独使用,也可以和webpack一起使用。
单独使用Babel
我们需要安装@babel/core和@babel/cli,一个是核心代码,一个是可以让我们在命令行使用babel命令。
1 | npm install @babel/core @babel/cli -D |
在命令行使用babel命令:
1 | # npx babel 文件夹/文件 --out-dir 转换后的文件夹 |
Babel使用插件
Babel本身的核心功能有限,它主要是作为转换器引擎,本身并不包含任何具体的语法转换规则或功能,它需要通过插件来完成这些功能。
这里介绍几个插件:
| 插件 | 说明 |
|---|---|
| @babel/plugin-transform-arrow-functions | 将 ES2015 箭头函数编译为 ES5 |
| @babel/plugin-transform-block-scoping | 将 ES2015 块范围(const 和 let)编译为 ES5 |
使用插件方式:
1 | npx babel src --out-dir dist --plugins=@babel/plugin-transform-arrow-functions,@babel/plugin-transform-block-scoping |
Babel配置文件
对于上面的操作,每次我们使用,都需要写一大推配置项,而且上面的命令也只是使用了两个插件,如果要使用更多的插件,那么就比较麻烦了,这个时候我们可以使用配置文件来优化我们的操作。
我们可以看一下官方文档中关于配置文件的说明:https://babeljs.io/docs/configuration
由于我们测试的是对于项目的单个部分,我们就创建.babelrc.json配置文件了,填写格式如下:
1 | { |
但就如在postcss是提到的,我们总不能一个个的添加插件,babel官方给我们也提供了一个预设:@babel/preset-env。
对于预设的配置,我们需要使用persets项进行配置:
1 | { |
同时,针对于预设的命令行操作也需要进行修改:
1 | npx babel src --out-dir dist --presets=@babel/preset-env |
babel-loader
在webpack中使用Babel,需要使用babel-loader进行配置:
首先需要安装babel-loader:
1 | npm i babel-loader -D |
然后在webpack配置文件中进行配置:
1 | { |
通过babel-loader使用插件和预设
有两种方式:在UseEntry的options中进行配置和通过配置文件的方式进行配置。
通过配置文件的方式进行配置和前面一样,这里写一下options的写法:
1 | { |
1 | { |
webpack处理Vue代码
Vue代码明显不是js语言,我们必然需要一个loader处理Vue代码,这个loader就是[vue-loader](https://vue-loader.vuejs.org/zh/)。
首先当然还是对其进行安装:
1 | npm i vue-loader - D |
但想要使用vue-loader对vue文件进行处理,还需要安装@vue/compiler-sfc,因为vue-loader会使用@vue/compiler-sfc中的方法。
只需要安装@vue/compiler-sfc即可:
1 | npm i -D @vue/compiler-sfc |
同时我还需要在plugins模块引入vue-loader中的VuePluginLoader插件:
1 | // 引入VuePluginLoader插件 |
注意:我们还需要安装vue,因为我们需要为打包的文件提供一个能运行的vue环境,所以我们仍需进行:npm i vue操作。
resolve模块解析
resolver是一个帮忙寻找绝对路径的库,resolver 帮助 webpack 从每个 require/import 语句中,找到需要引入到 bundle 中的模块代码。 当打包模块时,webpack 使用 enhanced-resolve 来解析文件路径。
webpack能解析三种文件路径:
(1) 绝对路径
1 | import '/home/me/file'; |
由于已经获得文件的绝对路径,因此不需要再做进一步解析。
(2) 相对路径:
1 | import '../src/file1'; |
在这种情况下,使用 import 或 require 的资源文件所处的目录,被认为是上下文目录。在 import/require 中给定的相对路径,会拼接此上下文路径,来生成模块的绝对路径。
(3) 模块路径
1 | import 'module'; |
resolve.modules
在resolve.modules中指定的所有目录中检索模块,默认值是['node_modules'],所以对于模块路径,默认会从node_modules中检索,我们也可以自行指定,但其实也没啥必要。
resolve.alias
我们也可以通过配置别名的方式来替换初始模块路径,比如说我们有一个嵌套层级极深的文件,我们想要引入顶层文件,无论是使用相对路径还是绝对路径,填写起来都过于麻烦,举个例子:
1 | // src/utils/time.js |
经过上面这个例子,我们发现无论是相对路径还是绝对路径,写起来都过于冗长,我们可以通过webpack中的resolve.alias属性来解决这个问题:
1 | resolve: { |
引入time.js文件。
1 | import time from 'utilsTime'; |
resolve.mainFiles
但我们以路径的形式引入,但只引入到文件夹,webpack并不知道要引入该文件夹下的哪一个文件,这个时就可以通过resolve.mainFiles属性来解决。
1 | resolve: { |
其实mainFiles中配置的的文件后缀名也可以省略,这与resolve.extensions属性有关。
resolve.extensions
当我们引入文件时,我们不想写后缀名,想让webpack自动去寻找文件,比如:src/utils/run.js,我们引入时只写import run from './utils/run',要实现这个功能,需要配置resolve.extensions属性。
1 | resolve: { |
webpack插件
webpack官方对plugins的描述:
从上图我们可以看出,loader可以做的事情,plugins也可以做的事情,甚至还能做一些优化、压缩、打包等等事情。
我们先介绍几个常用的webpack插件,先使用一下:
HtmlWebpackPlugin
HtmlWebpackPlugin可以生成一个html文件,并自动引入打包后的js文件。
首先我们需要先安装html-webpack-plguin:
1 | npm i -D html-webpack-plugin |
然后在webpack.config.js配置文件中进行配置:
1 | plugins: [new HtmlWebpackPlugin()]; |
再次进行打包操作后就会在打包后的文件夹中生成一个index.html文件,并自动引入打包后的js文件。
对于HtmlWebpackPlugin生成的html模板,我们可能对其中的内容不太满意,我们有时可能希望使用我们自定义编写的文件,这个时候就需要对HtmlWebpackPlugin进行一些配置了。
自定义HTML模板
首先我们需要先编写一个html文件,这一步自己操作即可。
然后在webpack.config.js中配置HtmlWebpackPlugin,如下:
1 | plugins: [ |
然后就可以进行打包测试了。
自定义模板数据填充
对于我们编写的HTML模板,我们可以通过EJS的模板语法占位并进行填充,从这里我们可以看出,HtmlWebpackPlugin是通过EJS模板引擎来处理HTML模板的。
首先我们在模板中定义一个变量,对于这个变量,一定要通过htmlWebpackPlugin.options中获取,比如:
1 | <!-- title为插件中配置的变量名 --> |
我们再看一下 webpack.config.js 中的配置:
1 | plugins: [ |
CleanWebpackPlugin
CleanWebpackPlugin这个插件的作用是:在打包之前,先删除之前已打包的目录(如果存在),然后重新打包。
安装:
1 | npm i -D clean-webpack-plugin |
配置如下:
1 | plugins: [new CleanWebpackPlugin()]; |
output.clean
从webpack5.20版本开始,我们不需要再安装clean-webpack-plugin插件了,直接在webpack.config.js中的output中添加clean: true配置即可:
1 | output: { |
DefinePlugin
DefinePlugin是一个webpack内置的插件,用于在打包时定义全局变量。
1 | plugins: [ |
然后就可以在开发代码中使用全局变量test了。
注意:如果我们设置的全局变量值为字符串的话,需要用字符串嵌套一层,或使用JSON.stringify()转换一下,否则会将单层字符串中的值解析为变量,这是因为插件的工作机制是执行 代码文本替换,而不是直接注入变量值。
EnvironmentPlugin
EnvironmentPlugin是基于DefinePlugin的一个封装,就是DefinePlugin的一个子类,用于处理环境变量。
EnvironmentPlugin也是一个webpack内置的插件,EnvironmentPlugin 接受一个 key 数组或一个将其 keys 映射到其默认值的对象。
其实就是将EnvironmentPlugin中的key值,映射到process.env中的值。
如果缺少,它将搜索配置中提供的默认值。如果既未定义环境变量也未定义默认值,则会引发错误:“EnvironmentPlugin - ${key} 环境变量未定义 ”。
如下:在不进行其他操作的前提下,我们通过数组的方式,来配置需要注入的变量,但我们并未设置起默认值,在打包的时候就会出现上述错误,但是还是能运行,只不过通过process.env获取的值为undefined。
1 | plugins: [new EnvironmentPlugin(['NODE_ENV', 'DEBUG'])]; |
设置默认值:
1 | plugins: [ |
通过上面设置我们就可以正常获取了:
1 | console.log(process.env.NODE_ENV); // development |
上文我们说了,EnvironmentPlugin是DefinePlugin的子类,所以通过EnvironmentPlugin设置环境变量,实际上也是通过DefinePlugin实现的。
对于上述的操作,通过DefinePlugin实现如下:
1 | plugins: [ |
DotenvPlugin
DotenvPlugin是第三方插件,也是与环境变量有关的,用于加载.env文件,我们可以在.env文件中定义环境变量。
首先我们需要先安装dotenv-webpack:
1 | npm i -D detenv-webpack |
然后在webpack.config.js中添加如下配置:
1 | plugins: [new DotenvWebpackPlugin()]; |
然后我们就可以直接创建一个.env文件(这与配置项path的默认值有关),并定义环境变量:
1 | VUE_BASE_URL=/api/ |
然后就可以在开发代码中任意位置使用通过process.env.VUE_BASE_URL来获取环境变量了。
DotenvPlugin配置项
| 参数 | 描述 | 默认值 | 场景示例 |
|---|---|---|---|
| path | .env文件的路径 | ‘./.env’ | path: './.env.development' |
| safe | 安全模式(safe),验证.env文件包含所有.env.example中的变量 |
false | |
| allowEmptyValues | 是否safe下允许空字符串。如果为 false,则如果任何 env 变量为空,将引发错误(但前提是启用了安全模式) | false | |
| expand | 否解析变量中的嵌套值 | false | BASE_URL=example.com API_URL=$BASE_URL/api |
| prefix | 要在环境变量名称之前使用的前缀 | ‘process.env.’ | prefix: 'import.meta.env.' |
| systemvars | 如果您更愿意加载所有系统变量,请设置为 true(对于 CI 目的很有用) | false | |
| silent | 如果为 true,则将禁止显示所有警告 | false | |
| defaults | 添加对 dotenv-defaults 的支持 | false | |
| ignoreStub | 覆盖是否对 process.env 进行存根的自动检查 | false |
通过DotenvPlugin加载不同的.env.[environemt]配置文件
在项目开发中,我们通常会定义多个环境变量文件,里面配置相同项但不同值,以期许在不同的环境下使用不同的配置,我们可以利用DotenvPlugin的path实现。
对于.env.development和.env.production两个文件,只需要通过process.env.NODE_ENV环境变量就能指定使用哪个文件。`
注意:DotenvWebpackPlugin 默认不会覆盖已存在的 process.env.NODE_ENV 值,即通过mode设置过后,在.env中的NODE_ENV配置就不生效了。这是由 Node.js 环境变量的特性决定的,而不是插件本身的限制。
上述说的是默认不会覆盖,就是说可以覆盖,但我建议不要覆盖,这样可能导致构建系统行为异常,这里我就不说怎么操作覆盖了。
我们需要借助--env这个命令行参数,同时需要把配置文件改为导出一个函数,这样能接收到--env的参数:
1 | module.exports = (env) => { |
对于这个命令行参数填写也有一定的要求:
1 | # windows cmd 填写 |
接下来给出一个大概的配置文件内容:
1 | const path = require('path'); |
使用cross-env解决跨环境问题
[cross-env](https://www.npmjs.com/package/cross-env)是一个运行跨平台设置和使用环境变量的脚本。
因为我们在window、linux中运行命令时,环境变量的设置方式不同:
-
windows cmd:set NODE_ENV=development。 -
powershell:$env:NODE_ENV="development"。 -
linux:NODE_ENV=development或export NODE_ENV=development。
cross-env的出现可以实现跨环境设置环境变量,即一种命令可以在所有环境下运行。
安装cross-env:
1 | npm i cross-env -D |
命令行使用:
1 | # npx cross-env 环境变量 其他命令 |
上述命令可以在所有环境都能生效运行。
ProvidePlugin
ProvidePlugin是一个webpack的插件,用于自动加载模块,而无需在每个模块中手动引入,通过ProvidePlugin能帮助我们实现shimming(垫片)的效果。
ProvidePlugin的使用场景:
比如说我们在项目想使用axios这一个库,但我不想引入,同时我又没有对其进行全局设置,那么我们就可以使用ProvidePlugin解决这个问题。
1 | new ProvidePlugin({ |
webpack打包后注释模块的单独提取
在生产环境下,在我们引入第三方库进行打包时,我们会发现打包产物中可能会有一个xxx.LICENSE.txt文件,这主要涉及到法律合规性和开源许可证的要求,也时对开源作者的基本尊重。
webpack会自动帮我们进行提取,这与terser-webpack-plugin插件有关,在安装webpack的时候会自动帮我们进行安装。
我们不需要进行配置,因为在生产环境下,webpack会自动进行配置,内部配置如下:
1 | optimization: { |