webpack 概念

webpack 是一个 JavaScript 应用程序的 静态模块打包工具

这份文档最重要的是:你的 webpack 配置可以有许多不同的格式和风格。关键在于,为了便于你和你的团队易于理解和维护这些配置,需要保证一致性。

 

前言:本文档旨在给出这些概念的高度概述,同时提供具体概念的详尽相关用例。

 

目录

一、核心概念

1、入口(entry)

2、输出(output)

(1)、低配

(2)、中配

(3)、高配

3、模式(mode)

(1)、用法

(2)、如何根据 webpack.config.js 中的 mode 变量更改打包模式?

4、loader

(1)、(推荐)在 webpack.config.js 文件中指定 loader

(2)、在每个 import 语句中显式指定 loader

(3)、在 shell 命令中指定loader

5、插件(plugin)

(1)、机制原理

(2)、用法 

①、配置 webpack.config.js

②、Node API 

6、浏览器兼容性

7、部署目标

(1)、基础用法

(2)、多个 target 

(3)、资源 

8、模块热替换

二、了解运作机制

三、配置webpack的注意事项

 


一、核心概念

1、入口(entry)

入口指的是:webpack 应该使用哪个模块,来作为构建其内部 依赖图 的开始。

默认值是: ./src/index.js。

你可以通过在 webpack configuration 中配置 entry 属性,来指定一个(或多个)不同的入口起点。

每个 HTML 文档只使用一个入口起点。

webpack.config.js

module.exports = {
  entry: {
    app: './src/app.js',
    adminApp: './src/adminApp.js'
  }
};

 

2、输出(output)

输出指的是: 控制 webpack 如何向硬盘写入编译文件(bundle),以及如何命名这些文件。

输出文件的默认值是: ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中。

你可以通过在配置中指定一个 output 字段,来配置这些处理过程。

即使可以存在多个 entry 起点,也只能指定一个 output 配置。

(1)、低配

在 webpack 中配置 output 属性的最低要求是,将它的值设置为一个对象,包括以下属性:

  • filename 用于输出文件的文件名。

webpack.config.js

module.exports = {
  output: {
    filename: 'bundle.js',
  }
};

此配置将一个单独的 bundle.js 文件输出到 dist 目录中。

(2)、中配

多个入口起点 

如果配置创建了多个单独的 "chunk"(例如,使用多个入口起点或使用像 CommonsChunkPlugin 这样的插件),则应该使用 占位符(substitutions) 来确保每个文件具有唯一的名称。

module.exports = {
  entry: {
    app: './src/app.js',
    search: './src/search.js'
  },
  output: {
    filename: '[name].js',
    path: __dirname + '/dist'
  }
};

// 写入到硬盘:./dist/app.js, ./dist/search.js

(3)、高配

高级进阶 

以下是对资源使用 CDN 和 hash 的复杂示例:

config.js

module.exports = {
  //...
  output: {
    path: '/home/proj/cdn/assets/[hash]',
    publicPath: 'http://cdn.example.com/assets/[hash]/'
  }
};

如果在编译时,不知道最终输出文件的 publicPath 是什么地址,则可以将其留空,并且在运行时通过入口起点文件中的 __webpack_public_path__ 动态设置。

__webpack_public_path__ = myRuntimePublicPath;

// 应用程序入口的其余部分

 

3、模式(mode)

提供 mode 配置选项,告知 webpack 使用相应环境的内置优化。

值包括:none, development 或 production(默认)。

(1)、用法

只需在配置对象中提供 mode 选项:

module.exports = {
  mode: 'production'
};

或者从 CLI 参数中传递:

webpack --mode=production

支持以下字符串值:

选项

描述

Development

会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development。

启用 NamedChunksPlugin 和 NamedModulesPlugin。

Production

会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。

启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 TerserPlugin。

None

退出任何默认优化选项

(2)、如何根据 webpack.config.js 中的 mode 变量更改打包模式?

如果要根据 webpack.config.js 中的 mode 变量更改打包行为,则必须将配置导出为一个函数,而不是导出为一个对象:

var config = {
  entry: './app.js'
  //...
};

module.exports = (env, argv) => {

  if (argv.mode === 'development') {
    config.devtool = 'source-map';
  }

  if (argv.mode === 'production') {
    //...
  }

  return config;
};

4、loader

webpack 只能理解 JavaScript 和 JSON 文件。

loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。

loader 运行在 Node.js 中,支持任何 Node.js 能做到的操作。

在你的应用程序中,有 三种 使用 loader 的方式:

  • 配置(推荐):在 webpack.config.js 文件中指定 loader。
  • 内联:在每个 import 语句中显式指定 loader。
  • CLI:在 shell 命令中指定它们。

(1)、(推荐)在 webpack.config.js 文件中指定 loader

这样展示 loader ,让你对各个 loader 有个全局概览,易于维护。

在 module.rules 中配置,允许指定多个 loader。

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          { loader: 'style-loader' },
          {
            loader: 'css-loader',
            options: {
              modules: true
            }
          },
          { loader: 'sass-loader' }
        ]
      }
    ]
  }
};

在use数组中,loader 从右到左地  “取值-->执行” 。在上面的示例中,从 sass-loader 开始执行,然后继续执行 css-loader,最后以 style-loader 为结束。查看 loader 功能 了解有关 loader 顺序的更多信息。

(2)、在每个 import 语句中显式指定 loader

可以在 import 语句或任何 等同于 "import" 的方法 中指定 loader。使用 ! 将资源中的 loader 分开。每个部分都会相对于当前目录解析。

import Styles from 'style-loader!css-loader?modules!./styles.css';
  • 使用 ! 为整个规则添加前缀,可以覆盖配置中的所有 loader 定义。
  • 选项可以传递查询参数,例如 ?key=value&foo=bar,或者一个 JSON 对象,例如 ?{"key":"value","foo":"bar"}

(3)、在 shell 命令中指定loader

webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'

这会对 .jade 文件使用 jade-loader,以及对 .css 文件使用 style-loader 和 css-loader

 

5、插件(plugin)

插件是 webpack 的支柱功能,插件目的在于解决 loader 无法实现的其他事,包括:打包优化,资源管理,注入环境变量。

想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建它的一个实例。

(1)、机制原理

webpack 插件是一个具有 apply 方法的 JavaScript 对象。apply 方法会被 webpack compiler 调用,并且 compiler 对象可在整个编译生命周期访问。

ConsoleLogOnBuildWebpackPlugin.js

const pluginName = 'ConsoleLogOnBuildWebpackPlugin';

class ConsoleLogOnBuildWebpackPlugin {
  apply(compiler) {
    compiler.hooks.run.tap(pluginName, compilation => {
      console.log('webpack 构建过程开始!');
    });
  }
}

compiler hook 的 tap 方法的第一个参数,应该是驼峰式命名的插件名称。建议为此使用一个常量,以便它可以在所有 hook 中复用。

(2)、用法 

由于插件可以携带参数/选项,你必须在 webpack 配置中,向 plugins 属性传入 new 实例。

根据你使用 webpack 的需要,这里有多种方式使用插件。

①、配置 webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); //通过 npm 安装
const webpack = require('webpack'); //访问内置的插件
const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    filename: 'my-first-webpack.bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: 'babel-loader'
      }
    ]
  },
  plugins: [
    new webpack.ProgressPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

②、Node API 

在使用 Node API 时,还可以通过配置中的 plugins 属性传入插件。

some-node-script.js

const webpack = require('webpack'); //访问 webpack 运行时(runtime)
const configuration = require('./webpack.config.js');

let compiler = webpack(configuration);

new webpack.ProgressPlugin().apply(compiler);

compiler.run(function(err, stats) {
  // ...
});

 

6、浏览器兼容性

webpack 支持所有符合 ES5 标准 的浏览器(不支持 IE8 及以下版本)。webpack 的 import() 和 require.ensure() 需要 Promise。如果你想要支持旧版本浏览器,在使用这些表达式之前,还需要 提前加载 polyfill

 

7、部署目标

因为服务器和浏览器代码都可以用 JavaScript 编写,所以 webpack 提供了多种部署 target(目标),你可以在你的 webpack 配置对象 中进行设置。

(1)、基础用法

webpack.config.js

module.exports = {
  target: 'node'
};

每个 target 都有各种部署(deployment)/环境(environment)特定的附加项,以支持满足其需求。查看 target 可用值

(2)、多个 target 

虽然 webpack 不支持向 target 传入多个字符串,还是可以通过打包两个单独配置,来创建出一个同构的 library:

webpack.config.js

const path = require('path');
const serverConfig = {
  target: 'node',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'lib.node.js'
  }
  //…
};

const clientConfig = {
  target: 'web', // <=== 默认是 'web',可省略
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'lib.js'
  }
  //…
};

module.exports = [ serverConfig, clientConfig ];

上面的例子将在 dist 文件夹下创建 lib.js 和 lib.node.js 文件。

(3)、资源 

从上面的选项能够看出,可以选择多种不同的部署 target。下面是一个示例列表,以及可以参考的资源。

 

8、模块热替换

模块热替换(HMR)功能会在应用程序运行过程中,替换、添加或删除 模块,而无需重新加载整个页面。主要是通过以下几种方式,来显著加快开发速度:

  • 保留在完全重新加载页面期间丢失的应用程序状态。
  • 只更新变更内容,以节省宝贵的开发时间。
  • 在源代码中对 CSS/JS 进行修改,会立刻在浏览器中进行更新,这几乎相当于在浏览器 devtools 直接更改样式。

这一切是如何运行的(原理)?请戳此链接:https://webpack.docschina.org/concepts/hot-module-replacement/

 


二、了解运作机制

为了更好地理解模块打包工具背后的理念,以及在底层它们是如何运作的,请参考以下资源:

 


三、配置webpack的注意事项

  • 在使用 webpack 命令行接口(CLI)时,访问命令行接口(CLI)参数(应该编写自己的命令行接口(CLI),或 使用 --env)
  • 导出不确定的值(调用 webpack 两次应该产生同样的输出文件)
  • 编写很长的配置(应该将配置拆分为多个文件)

 

 

后记:

1、待回头研究的技能点:使用webpack可预测的长效缓存:https://webpack.docschina.org/concepts/manifest/

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值