前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入了解Webpack

深入了解Webpack

原创
作者头像
ruochen
发布2021-11-26 13:07:27
6.9K0
发布2021-11-26 13:07:27
举报
文章被收录于专栏:若尘的技术专栏

Webpack的开发和生产构建

本质上,有两种构建JavaScript应用程序的模式:开发和生产。以前,您已使用开发模式在本地开发环境中开始使用Webpack Dev

Server。您可以更改源代码,Webpack再次将其捆绑,Webpack Dev Server会在浏览器中向您显示最新的开发版本。

但是,最终您希望拥有在Web服务器上的生产环境中部署Web应用程序所需的所有构建文件。由于Webpack将所有JavaScript源代码捆绑到一个

dist / index.html 文件中链接的 bundle.js 文件中,因此从 本质上讲

,您只需要Web服务器上的这两个文件即可向任何人显示Web应用程序。让我们看看如何为您创建两个文件。

首先,您已经有了 dist / index.html 文件。如果打开它,您已经看到它使用了 webpack 创建的bundle.js文件,该文件是

src / 文件夹中所有JavaScript源代码文件中的文件。

代码语言:txt
复制
<!DOCTYPE html>
代码语言:txt
复制
<html>
代码语言:txt
复制
  <head>
代码语言:txt
复制
    <title>Hello Webpack bundled JavaScript Project</title>
代码语言:txt
复制
  </head>
代码语言:txt
复制
  <body>
代码语言:txt
复制
    <div>
代码语言:txt
复制
      <h1>Hello Webpack bundled JavaScript Project</h1>
代码语言:txt
复制
    </div>
代码语言:txt
复制
    <script src="./bundle.js"></script>
代码语言:txt
复制
  </body>
代码语言:txt
复制
</html>

其次,如果键入npm start,则Webpack将动态创建此 bundle.js 文件,该文件将用于Webpack Dev

Server在开发模式下启动您的应用程序。您从未真正看到过 bundle.js 文件。

代码语言:txt
复制
{
代码语言:txt
复制
  ...
代码语言:txt
复制
  "scripts": {
代码语言:txt
复制
    "start": "webpack serve --config ./webpack.config.js --mode development",
代码语言:txt
复制
    "test": "echo \"Error: no test specified\" && exit 0"
代码语言:txt
复制
  },
代码语言:txt
复制
  ...
代码语言:txt
复制
}

现在,让我们介绍第二个npm脚本,以实际构建用于生产的应用程序。我们将显式使用Webpack而不是Webpack Dev

Server来捆绑所有JavaScript文件,重用以前的相同Webpack配置,还介绍了生产模式:

代码语言:txt
复制
{
代码语言:txt
复制
  ...
代码语言:txt
复制
  "scripts": {
代码语言:txt
复制
    "start": "webpack serve --config ./webpack.config.js --mode development",
代码语言:txt
复制
    "build": "webpack --config ./webpack.config.js --mode production",
代码语言:txt
复制
    "test": "echo \"Error: no test specified\" && exit 0"
代码语言:txt
复制
  },
代码语言:txt
复制
  ...
代码语言:txt
复制
}

如果运行npm run build,您将看到Webpack如何为您捆绑所有文件。一旦脚本经历了成功,你可以看到 DIST / bundle.js

在飞行中不生成的文件,但在你真正的创建 DIST / 文件夹。

剩下的唯一事情就是现在将 dist / 文件夹上传到Web服务器。但是,为了在本地检查 dist /

文件夹是否具有在远程Web服务器上运行应用程序所需的一切,请使用本地Web服务器(https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Findexzero%2Fhttp-

server)亲自进行尝试:

代码语言:txt
复制
npx http-server dist

它应该输出一个URL,您可以在浏览器中访问它。如果一切正常,您可以将 dist / 文件夹及其内容上载到Web服务器。

另请注意,Webpack开发和生产模式具有其自己的默认配置。开发模式在创建源代码文件时会考虑改善的开发人员体验,而生产版本会对源代码进行所有优化。

如何管理您的Webpack构建文件夹

每次运行npm run build,您都会看到Webpack使用 dist / bundle.js 文件创建新版本的bundle

JavaScript源代码。最终,您的Webpack构建管道将变得更加复杂,并且最终在 dist /

文件夹中包含两个以上的文件。突然,文件夹变得一团糟,因为您不知道哪些文件属于最新版本。最好的办法是,在每个Webpack构建中都从一个空的 dist /

文件夹开始。

假设我们要在每个Webpack构建中擦除 dist / 文件夹。这将意味着我们自动生成的 dist / bundle.js

文件将被删除(好),而我们手动实现的 dist / index.html

文件将被删除(不好)。我们不想为每个Webpack构建都手动重新创建此文件。为了自动生成 dist / index.html

文件,我们可以使用Webpack插件。首先,从项目的根目录安装[html-webpack-

plugin插件](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fjantimon%2Fhtml-

webpack-plugin)作为dev依赖项:

代码语言:txt
复制
npm install --save-dev html-webpack-plugin

成功安装后,在Webpack webpack.config.js 文件中引入Webpack插件:

代码语言:txt
复制
const path = require('path');
代码语言:txt
复制
const HtmlWebpackPlugin = require('html-webpack-plugin');
代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  entry: path.resolve(__dirname, './src/index.js'),
代码语言:txt
复制
  module: {
代码语言:txt
复制
    rules: [
代码语言:txt
复制
      {
代码语言:txt
复制
        test: /\.(js)$/,
代码语言:txt
复制
        exclude: /node_modules/,
代码语言:txt
复制
        use: ['babel-loader'],
代码语言:txt
复制
      },
代码语言:txt
复制
    ],
代码语言:txt
复制
  },
代码语言:txt
复制
  resolve: {
代码语言:txt
复制
    extensions: ['*', '.js'],
代码语言:txt
复制
  },
代码语言:txt
复制
  output: {
代码语言:txt
复制
    path: path.resolve(__dirname, './dist'),
代码语言:txt
复制
    filename: 'bundle.js',
代码语言:txt
复制
  },
代码语言:txt
复制
  plugins: [new HtmlWebpackPlugin()],
代码语言:txt
复制
  devServer: {
代码语言:txt
复制
    contentBase: path.resolve(__dirname, './dist'),
代码语言:txt
复制
  },
代码语言:txt
复制
};

现在,npm run build再次运行,看看它如何自动生成一个新的 dist / index.html

文件。它带有一个默认模板,用于说明文件的结构方式和文件中应包含的内容。但是,如果要为 dist / index.html

文件提供自定义内容,则可以自己指定模板:

代码语言:txt
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')
代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  ...
代码语言:txt
复制
  plugins: [
代码语言:txt
复制
    new HtmlWebpackPlugin({
代码语言:txt
复制
      title: 'Hello Webpack bundled JavaScript Project',
代码语言:txt
复制
      template: path.resolve(__dirname, './src/index.html'),
代码语言:txt
复制
    })
代码语言:txt
复制
  ],
代码语言:txt
复制
  ...
代码语言:txt
复制
};

然后,在您的源代码文件夹中创建一个新的 src / index.html 模板文件,并为其提供以下内容:

代码语言:txt
复制
<!DOCTYPE html>
代码语言:txt
复制
<html>
代码语言:txt
复制
  <head>
代码语言:txt
复制
    <title><%= htmlWebpackPlugin.options.title %></title>
代码语言:txt
复制
  </head>
代码语言:txt
复制
  <body>
代码语言:txt
复制
    <div>
代码语言:txt
复制
      <h1><%= htmlWebpackPlugin.options.title %></h1>
代码语言:txt
复制
      <div id="app">
代码语言:txt
复制
    </div>
代码语言:txt
复制
  </body>
代码语言:txt
复制
</html>

请注意,您不再需要使用 bundle.js

文件指定script标记,因为Webpack会自动为您引入脚本标记。还要注意,您不一定需要id属性和div容器,但在上一教程中我们已使用它在其上执行一些JavaScript。

现在,npm run build再次运行,查看新的自动生成的 dist / index.html是否src / index.html

中的模板匹配。最后,我们已经能够使用Webpack自动创建 dist / bundle.jsdist / index.html

这两个文件。这意味着我们可以在每个Webpack版本中删除 dist / 文件夹中的内容。为此,请引入[clean-webpack-

plugin插件](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fjohnagan%2Fclean-

webpack-plugin):

代码语言:txt
复制
npm install --save-dev clean-webpack-plugin

然后在您的 webpack.config.js 文件中引入它:

代码语言:txt
复制
const path = require('path');
代码语言:txt
复制
const HtmlWebpackPlugin = require('html-webpack-plugin');
代码语言:txt
复制
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  ...
代码语言:txt
复制
  plugins: [
代码语言:txt
复制
    new CleanWebpackPlugin(),
代码语言:txt
复制
    new HtmlWebpackPlugin({
代码语言:txt
复制
      title: 'Hello Webpack bundled JavaScript Project',
代码语言:txt
复制
      template: path.resolve(__dirname, './src/index.html'),
代码语言:txt
复制
    }),
代码语言:txt
复制
  ],
代码语言:txt
复制
  ...
代码语言:txt
复制
};

现在,每个Webpack构建都将擦除 dist / 文件夹的内容,然后从头开始创建新的 dist / index.html 和 _dist /

bundle.js 文件。通过这种方式进行设置,您将永远不会在 _dist / 文件夹中找到来自较旧Webpack构建的文件,这非常适合仅将整个

dist / 文件夹投入生产。

_注意:如果使用的是GitHub之(https://links.jianshu.com/go?to=https%3A%2F%2Fwww.robinwieruch.de%2Fgit-

essential-commands%2F)类的版本控制系统,则可以将构建文件夹(dist

/)放入.gitignore文件中,因为无论如何,所有内容都是自动生成的。某人获得您的项目的副本后,该人可以执行npm run build以生成文件。_

Webpack source map

Webpack捆绑了所有JavaScript源代码文件。但这很完美,但是它给我们作为开发人员带来了一个陷阱。一旦引入了错误并在浏览器的开发人员工具中看到了该错误,通常很难跟踪该错误发生的文件,因为Webpack将所有内容捆绑到一个JavaScript文件中。例如,假设我们的

src / index.js 文件从另一个文件导入了一个函数并使用了它:

代码语言:txt
复制
import sum from './sum.js';
代码语言:txt
复制
console.log(sum(2, 5));

在我们的 src / sum.js中 ,我们导出了此JavaScript函数,但不幸的是其中引入了一个错字:

代码语言:txt
复制
export default function (a, b) {
代码语言:txt
复制
  return a + c;
代码语言:txt
复制
};

如果npm start在浏览器中运行并打开该应用程序,则应该在开发人员工具中看到发生的错误:

代码语言:txt
复制
sum.js:3 Uncaught ReferenceError: c is not defined
代码语言:txt
复制
    at eval (sum.js:3)
代码语言:txt
复制
    at eval (index.js:4)
代码语言:txt
复制
    at Module../src/index.js (bundle.js:457)
代码语言:txt
复制
    at __webpack_require__ (bundle.js:20)
代码语言:txt
复制
    at eval (webpack:///multi_(:8080/webpack)-dev-server/client?:2:18)
代码语言:txt
复制
    at Object.0 (bundle.js:480)
代码语言:txt
复制
    at __webpack_require__ (bundle.js:20)
代码语言:txt
复制
    at bundle.js:84
代码语言:txt
复制
    at bundle.js:87

如果单击发生错误的 sum.js 文件,则只会看到Webpack的捆绑输出。在此示例的情况下,它仍然可读,但是请想象输出一个更复杂的问题:

代码语言:txt
复制
__webpack_require__.r(__webpack_exports__);
代码语言:txt
复制
/* harmony default export */ __webpack_exports__["default"] = (function (a, b) {
代码语言:txt
复制
  return a + c;
代码语言:txt
复制
});
代码语言:txt
复制
;

进一步执行此步骤,并在您的Webpack构建中引入该错误以进行生产。运行,npm run build然后`npx http-server

dist`再次在浏览器中看到错误:

代码语言:txt
复制
bundle.js:1 Uncaught ReferenceError: c is not defined
代码语言:txt
复制
    at Module.<anonymous> (bundle.js:1)
代码语言:txt
复制
    at t (bundle.js:1)
代码语言:txt
复制
    at bundle.js:1
代码语言:txt
复制
    at bundle.js:1

这次,它隐藏在 bundle.js 文件中,而没有让您知道导致它的实际文件。此外,一旦单击 bundle.js

文件,您只会看到Webpack捆绑的JavaScript生产版本,其格式不是可读的。

总之,这不是一个很好的开发人员体验,因为Webpack捆绑的JavaScript文件查找错误变得更加困难。对于开发模式,这是正确的,但对于生产模式,则更是如此。

为了克服此问题,可以引入[ source

map](https://links.jianshu.com/go?to=https%3A%2F%2Fwebpack.js.org%2Fconfiguration%2Fdevtool%2F),以为Webpack提供对原始源代码的引用。通过使用

source map,Webpack可以将所有捆绑的源代码映射回原始源。在您的 webpack.config.js 文件中,为 source

map引入一种常见配置:

代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  ...
代码语言:txt
复制
  devtool: 'source-map',
代码语言:txt
复制
};

之后,与仍然在源代码中的bug,运行npm run build和`npx http-server

dist`试。在浏览器中,请注意如何将错误跟踪到导致文件 sum.js

代码语言:txt
复制
sum.js:2 Uncaught ReferenceError: c is not defined
代码语言:txt
复制
    at Module.<anonymous> (sum.js:2)
代码语言:txt
复制
    at t (bootstrap:19)
代码语言:txt
复制
    at bootstrap:83
代码语言:txt
复制
    at bootstrap:83

单击文件将为您提供实际的源代码和错误的位置,即使Webpack捆绑了所有JavaScript源代码也是如此。还要注意,有一个名为 _dist /

bundle.js.map 的新文件,该文件用于执行 _src /中的 实际源代码和 dist / bundle.js中

的捆绑JavaScript的 映射

Webpack开发/构建配置

到目前为止,我们已经使用一种通用的Webpack配置进行开发和生产。但是,我们也可以为每种模式介绍一个配置。在 package.json中

,将启动脚本和构建脚本更改为以下内容:

代码语言:txt
复制
{
代码语言:txt
复制
  ...
代码语言:txt
复制
  "scripts": {
代码语言:txt
复制
    "start": "webpack serve --config ./webpack.dev.js",
代码语言:txt
复制
    "build": "webpack --config ./webpack.prod.js",
代码语言:txt
复制
    "test": "echo \"Error: no test specified\" && exit 0"
代码语言:txt
复制
  },
代码语言:txt
复制
  ...
代码语言:txt
复制
}

现在创建这两个新文件,将旧的 webpack.config.js 配置复制并粘贴到两个文件中,然后删除旧的 webpack.config.js

文件。接下来,由于我们在npm脚本中省略了Webpack模式,因此请为每个Webpack配置文件再次介绍它们。首先, webpack.dev.js

文件:

代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  mode: 'development',
代码语言:txt
复制
  ...
代码语言:txt
复制
};

其次, webpack.prod.js 文件:

代码语言:txt
复制
...
代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  mode: 'production',
代码语言:txt
复制
  ...
代码语言:txt
复制
};

您用于启动和构建应用程序的npm脚本应该可以再次工作。但是您可能会想:现在有什么区别?除了我们之前动态传递的Webpack模式外,Webpack的配置对于开发和生产都是相同的。我们甚至引入了不必要的重复。稍后再详细介绍后者。

在不断增长的Webpack配置中,您将介绍在开发和生产中行为应有所不同的内容(例如,插件,规则, source map)。例如,让我们来看一下我们先前实现的

source map。为大型代码库创建 source map文件是一项性能沉重的过程。为了使开发构建快速有效地运行,以提供出色的开发人员体验,您希望开发中的

source map不像生产构建中的 source map那样100%有效。为开发模式创建它们应该更快。因此,您可以对 webpack.dev.js

文件进行首次更改,而该更改不会反映在生产配置中:

代码语言:txt
复制
...
代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  mode: 'development',
代码语言:txt
复制
  ...
代码语言:txt
复制
  devtool: 'eval-source-map',
代码语言:txt
复制
};

现在,对于您的开发和生产模式, source map的生成方式有所不同,因为在两个Webpack配置文件中以不同的方式定义了 source

map。这只是在开发和生产中为Webpack配置不同配置的一个实例。

Webpack合并配置

目前,用于开发和生产的Webpack配置文件共享许多常用配置。如果我们能够将通用配置提取到一个单独的但常用的文件中,而仅根据开发和生产选择额外的特定配置,该怎么办?让我们通过调整

package.json 文件来做到这一点:

代码语言:txt
复制
{
代码语言:txt
复制
  ...
代码语言:txt
复制
  "scripts": {
代码语言:txt
复制
    "start": "webpack serve --config build-utils/webpack.config.js --env env=dev",
代码语言:txt
复制
    "build": "webpack --config build-utils/webpack.config.js --env env=prod",
代码语言:txt
复制
    "test": "echo \"Error: no test specified\" && exit 0"
代码语言:txt
复制
  },
代码语言:txt
复制
  ...
代码语言:txt
复制
}

如您所见,我们为两个npm脚本引用了一个新的共享 webpack.config.js 。该文件位于新的 build-utils

文件夹中。为了稍后在Webpack配置中区分正在运行的脚本,我们还向配置传递了一个环境标志(dev,prod)。

现在,再次创建共享的 build-utils / webpack.config.js 文件,但这一次是在新的专用 build-utils

文件夹中,并为其进行以下配置:

代码语言:txt
复制
const { merge } = require('webpack-merge');
代码语言:txt
复制
const commonConfig = require('./webpack.common.js');
代码语言:txt
复制
module.exports = ({ env }) => {
代码语言:txt
复制
  const envConfig = require(`./webpack.${env}.js`);
代码语言:txt
复制
  return merge(commonConfig, envConfig);
代码语言:txt
复制
};

您可以看到该函数env从npm脚本接收了我们的环境标志。这样,我们可以动态地需要一个具有JavaScript模板文字的(https://links.jianshu.com/go?to=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-

US%2Fdocs%2FWeb%2FJavaScript%2FReference%2FTemplate_literals)特定于环境的Webpack配置文件,并将其与通用的Webpack配置合并。为了合并它,让我们安装一个小助手库:

代码语言:txt
复制
npm install --save-dev webpack-merge

接下来,我们现在必须在 build-utils 文件夹中实现三个文件:

  • webpack.common.js:用于开发和构建模式的共享Webpack配置。
  • webpack.dev.js:Webpack配置仅由开发模式使用。
  • webpack.prod.js:Webpack配置仅由生产模式使用。

让我们从新的 build-utils / webpack.common.js 文件中的共享Webpack配置开始:

代码语言:txt
复制
const path = require('path');
代码语言:txt
复制
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
代码语言:txt
复制
const HtmlWebpackPlugin = require('html-webpack-plugin')
代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  entry: path.resolve(__dirname, '..', './src/index.js'),
代码语言:txt
复制
  module: {
代码语言:txt
复制
    rules: [
代码语言:txt
复制
      {
代码语言:txt
复制
        test: /\.(js)$/,
代码语言:txt
复制
        exclude: /node_modules/,
代码语言:txt
复制
        use: ['babel-loader']
代码语言:txt
复制
      }
代码语言:txt
复制
    ]
代码语言:txt
复制
  },
代码语言:txt
复制
  resolve: {
代码语言:txt
复制
    extensions: ['*', '.js']
代码语言:txt
复制
  },
代码语言:txt
复制
  plugins: [
代码语言:txt
复制
    new CleanWebpackPlugin(),
代码语言:txt
复制
    new HtmlWebpackPlugin({
代码语言:txt
复制
      title: 'Hello Webpack bundled JavaScript Project',
代码语言:txt
复制
      template: path.resolve(__dirname, '..', './src/index.html'),
代码语言:txt
复制
    })
代码语言:txt
复制
  ],
代码语言:txt
复制
  output: {
代码语言:txt
复制
    path: path.resolve(__dirname, '..', './dist'),
代码语言:txt
复制
    filename: 'bundle.js'
代码语言:txt
复制
  },
代码语言:txt
复制
  devServer: {
代码语言:txt
复制
    contentBase: path.resolve(__dirname, '..', './dist'),
代码语言:txt
复制
  },
代码语言:txt
复制
};

请注意,与以前的Webpack配置相比,某些文件路径已更改,因为我们现在在专用文件夹中拥有此文件。还要注意,没有Webpack模式,也没有 source

map。这两个选项将成为其专用Webpack配置文件中特定的环境(例如,开发,生产)。

通过创建 build-utils / webpack.dev.js 文件 继续进行 操作,并为其提供以下内容:

代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  mode: 'development',
代码语言:txt
复制
  devtool: 'eval-source-map',
代码语言:txt
复制
}

最后但并非最不重要的是,新的 build-utils / webpack.prod.js 文件接收以下内容:

代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  mode: 'production',
代码语言:txt
复制
  devtool: 'source-map',
代码语言:txt
复制
};

您的文件夹结构现在应该类似于以下内容。请注意,先前各节的 build-utils / 文件夹之外没有Webpack配置:

代码语言:txt
复制
- build-utils/
-- webpack.common.js
-- webpack.config.js
-- webpack.dev.js
-- webpack.prod.js
- dist/
-- bundle.js
-- bundle.js.map
-- index.html
- src/
-- index.html
-- index.js
- package.json
- .babelrc

您的npm startnpm run build脚本现在应该可以工作了。相对于其 build-utils / webpack.dev.js

build-utils / webpack.prod.js 配置文件,两者都针对Webpack模式和 source

map使用不同的配置。但是它们也共享来自 build-utils / webpack.common.js 的通用Webpack配置。一切都动态合并在

build-utils / webpack.config.js 文件中,该文件根据 package.json中 npm脚本中的传入标志进行动态合并。

Webpack环境变量:定义

有时您可能想在源代码中知道您是处于开发还是生产模式。对于这些情况,您可以通过Webpack指定动态环境变量。由于每个环境都有一个Webpack配置文件(开发,生产),因此可以为它们定义专用的环境变量。在您的

build-utils / webpack.dev.js中 ,通过以下方式定义环境变量:

代码语言:txt
复制
const { DefinePlugin } = require('webpack');
代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  mode: 'development',
代码语言:txt
复制
  plugins: [
代码语言:txt
复制
    new DefinePlugin({
代码语言:txt
复制
      'process.env': {
代码语言:txt
复制
        'NODE_ENV': JSON.stringify('development'),
代码语言:txt
复制
      }
代码语言:txt
复制
    }),
代码语言:txt
复制
  ],
代码语言:txt
复制
  devtool: 'eval-source-map',
代码语言:txt
复制
};

这同样适用于您的 build-utils / webpack.prod.js 文件,但具有不同的环境变量:

代码语言:txt
复制
const { DefinePlugin } = require('webpack');
代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  mode: 'production',
代码语言:txt
复制
  plugins: [
代码语言:txt
复制
    new DefinePlugin({
代码语言:txt
复制
      'process.env': {
代码语言:txt
复制
        'NODE_ENV': JSON.stringify('production'),
代码语言:txt
复制
      }
代码语言:txt
复制
    }),
代码语言:txt
复制
  ],
代码语言:txt
复制
  devtool: 'source-map',
代码语言:txt
复制
};

现在,您可以使用 src / index.js 文件中console.log(process.env.NODE_ENV);的环境变量或 _src

/_ 文件夹中的任何其他JavaScript来基于它进行决策。在这种情况下,您已经创建了两个不同的环境变量-

每个都针对Webpack模式。但是,将来您可能会为某些情况引入更多的环境变量。

Webpack环境变量:.ENV

以前,您开始在Webpack配置文件中定义环境变量。但是,这不是敏感信息的最佳实践。例如,假设您要根据开发或生产环境使用API密钥/秘密(凭证)来访问数据库。您不想在您的Webpack配置中公开这些敏感信息,而这些信息可能会与其他人共享。相反,您想为环境文件引入专用文件,这些文件可以与其他文件和版本控制系统(如Git或SVN)保持距离。

让我们从为开发和生产模式创建两个环境变量文件开始。第一个用于开发模式,称为 .env.development 。将其放入具有以下内容的项目的根目录中:

代码语言:txt
复制
NODE_ENV=development

第二个称为 .env.production 并具有其他内容。它还放置在项目的根目录中:

代码语言:txt
复制
NODE_ENV=production

通过使用[dotenv-

webpack插件](https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Fmrsteele%2Fdotenv-

webpack),您可以将这些环境变量复制到Webpack配置文件中。首先,安装插件:

代码语言:txt
复制
npm install dotenv-webpack --save-dev

其次,在开发模式的 build-utils / webpack.dev.js 文件中使用它:

代码语言:txt
复制
const path = require('path');
代码语言:txt
复制
const Dotenv = require('dotenv-webpack');
代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  mode: 'development',
代码语言:txt
复制
  plugins: [
代码语言:txt
复制
    new Dotenv({
代码语言:txt
复制
      path: path.resolve(__dirname, '..', './.env.development'),
代码语言:txt
复制
    })
代码语言:txt
复制
  ],
代码语言:txt
复制
  devtool: 'eval-source-map',
代码语言:txt
复制
};

第三,在生产模式的 build-utils / webpack.prod.js 文件中使用它:

代码语言:txt
复制
const path = require('path');
代码语言:txt
复制
const Dotenv = require('dotenv-webpack');
代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  mode: 'development',
代码语言:txt
复制
  plugins: [
代码语言:txt
复制
    new Dotenv({
代码语言:txt
复制
      path: path.resolve(__dirname, '..', './.env.production'),
代码语言:txt
复制
    })
代码语言:txt
复制
  ],
代码语言:txt
复制
  devtool: 'eval-source-map',
代码语言:txt
复制
};

现在,您可以通过 .env.development.env.production

文件在环境变量中引入敏感信息(例如IP地址,帐户凭据和API密钥/秘密)。您的Webpack配置将复制它们,以使其在您的源代码中可访问(请参阅上一节)。如果您使用的是版本控制系统(例如Git),请不要忘记将这些新的

.env 文件添加到您的 .gitignore中 ,以向第三方隐藏您的敏感信息。

Webpack插件

Webpack具有庞大的插件生态系统。通过使用Webpack开发或生产模式已经隐式使用了其中的几个。但是,还有其他Webpack插件可以改善您的Webpack捆绑包体验。例如,让我们介绍可用于分析和可视化Webpack捆绑包的加载项。在

package.json中 ,为您的构建过程引入一个新的npm脚本,但是这次使用Webpack插件:

代码语言:txt
复制
{
代码语言:txt
复制
  ...
代码语言:txt
复制
  "scripts": {
代码语言:txt
复制
    "start": "webpack serve --config build-utils/webpack.config.js --env env=dev",
代码语言:txt
复制
    "build": "webpack --config build-utils/webpack.config.js --env env=prod",
代码语言:txt
复制
    "build:analyze": "npm run build -- --env addon=bundleanalyze",
代码语言:txt
复制
    "test": "echo \"Error: no test specified\" && exit 0"
代码语言:txt
复制
  },
代码语言:txt
复制
  ...
代码语言:txt
复制
}

请注意,这个新的npm脚本如何运行另一个npm脚本,但是具有附加配置(此处是Webpack插件)。但是,Webpack插件不会神奇地运行。在这种情况下,它们仅作为标志传递给我们的Webpack配置。让我们看看如何在

build-utils / webpack.config.js 文件中使用它们:

代码语言:txt
复制
const { merge } = require('webpack-merge');
代码语言:txt
复制
const commonConfig = require('./webpack.common.js');
代码语言:txt
复制
const getAddons = (addonsArgs) => {
代码语言:txt
复制
  const addons = Array.isArray(addonsArgs)
代码语言:txt
复制
    ? addonsArgs
代码语言:txt
复制
    : [addonsArgs];
代码语言:txt
复制
  return addons
代码语言:txt
复制
    .filter(Boolean)
代码语言:txt
复制
    .map((name) => require(`./addons/webpack.${name}.js`));
代码语言:txt
复制
};
代码语言:txt
复制
module.exports = ({ env, addon }) => {
代码语言:txt
复制
  const envConfig = require(`./webpack.${env}.js`);
代码语言:txt
复制
  return merge(commonConfig, envConfig, ...getAddons(addon));
代码语言:txt
复制
};

现在,不仅合并了通用的和特定于环境的Webpack配置,而且还合并了可选的附加组件,我们将它们放入专用的 build-utils / addons

文件夹中。让我们从 build-utils / addons / webpack.bundleanalyze.js 文件开始:

代码语言:txt
复制
const path = require('path');
代码语言:txt
复制
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
代码语言:txt
复制
module.exports = {
代码语言:txt
复制
  plugins: [
代码语言:txt
复制
    new BundleAnalyzerPlugin({
代码语言:txt
复制
      analyzerMode: 'static',
代码语言:txt
复制
      reportFilename: path.resolve(
代码语言:txt
复制
        __dirname,
代码语言:txt
复制
        '..',
代码语言:txt
复制
        '..',
代码语言:txt
复制
        './dist/report.html'
代码语言:txt
复制
      ),
代码语言:txt
复制
      openAnalyzer: false,
代码语言:txt
复制
    }),
代码语言:txt
复制
  ],
代码语言:txt
复制
};

接下来,在命令行上通过npm安装Webpack插件:

代码语言:txt
复制
npm install --save-dev webpack-bundle-analyzer

如您所见,您已经在新的 build-utils / addons /

文件夹中引入了一个特定的Webpack插件,可以选择添加该Webpack插件。插件文件的命名与 package.json中

npm脚本传递的标志匹配。您的Webpack合并确保将所有传递的插件标记添加为Webpack配置中的实际插件。

现在,请自己尝试用于Webpack分析和可视化的可选工具。在命令行上,键入npm run build:analyze。然后,检查您的 dist /

文件夹中是否有新文件。您应该找到一种可以通过以下方式打开的方式:

  • Webpack的bundleanalyze: dist / report.html
  • 通过打开npx http-server dist,访问URL,然后附加 /report.html

您将看到具有两种不同可视化效果的构建优化的Webpack捆绑包。您的应用程序中没有很多代码,但是一旦您在节点包管理器中引入了更多的源代码和更多的外部库(依赖项),您将看到Webpack包的大小将如何增长。最终,您将偶然地引入一个大型库,这会使您的应用程序变得太大。然后,分析工具和可视化工具都可以帮助您找到问题的根源。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • Webpack的开发和生产构建
  • 如何管理您的Webpack构建文件夹
  • Webpack source map
  • Webpack开发/构建配置
  • Webpack合并配置
  • Webpack环境变量:定义
  • Webpack环境变量:.ENV
  • Webpack插件
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档