webpack 笔记 概念篇

2019-12-10  本文已影响0人  秀秀_2d78

概念

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。
它会递归地构建一个依赖关系图(dependency graph),包含应用程序需要的每个模块,然后将这些模块打包成一个或多个 bundle。

一、入口(entry)

module.exports = {
  entry: './path/to/my/entry/file.js'
};

entry 属性的单个入口语法,是下面的简写:

const config = {
  entry: {
    main: './path/to/my/entry/file.js'
  }
};

分离 应用程序(app) 和 第三方库(vendor) 入口

const config = {
  entry: {
    app: './src/app.js',
    vendors: './src/vendors.js'
  }
};

这种方式比较常见于,只有一个入口起点(不包括 vendor)的单页应用程序中。

多页面应用程序
const config = {
  entry: {
    pageOne: './src/pageOne/index.js',
    pageTwo: './src/pageTwo/index.js',
    pageThree: './src/pageThree/index.js'
  }
};

为每个页面间的应用程序共享代码创建 bundle。由于入口起点增多,多页应用能够复用入口起点之间的大量代码/模块

根据经验:每个 HTML 文档只使用一个入口起点。

二、出口(output)

const config = {
  output: {
    filename: 'bundle.js',
    path: '/home/proj/public/assets'
  }
};
module.exports = config;

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

多个入口起点

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

{
  entry: {
    app: './src/app.js',
    search: './src/search.js'
  },
  output: {
    filename: '[name].js',
    path: __dirname + '/dist'
  }
}
// 写入到硬盘:./dist/app.js, ./dist/search.js

三、模式

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

四、loader

npm install --save-dev css-loader
npm install --save-dev ts-loader

然后指示 webpack 对每个 .css 使用 css-loader,以及对所有 .ts 文件使用 `ts-loadert

module.exports = {
  module: {
    rules: [
      { test: /\.css$/, use: 'css-loader' },
      { test: /\.ts$/, use: 'ts-loader' }
    ]
  }
};

在 webpack 配置中定义 loader 时,要定义在 module.rules 中
module.rules允许你在 webpack 配置中指定多个 loader。

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

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

import Styles from 'style-loader!css-loader?modules!./styles.css';

通过前置所有规则及使用 !,可以对应覆盖到配置中的任意 loader。

尽可能使用 module.rules,因为这样可以减少源码中的代码量,并且可以在出错时,更快地调试和定位 loader 中的问题。

loader 特性

五、插件(plugins)

module.exports = {
 plugins: [
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

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

即便使用 Node API,用户也应该在配置中传入 plugins 属性。compiler.apply 并不是推荐的使用方式。

六、配置(configuration)

因为 webpack 配置是标准的 Node.js CommonJS 模块,你可以做到以下事情:

虽然技术上可行,但应避免以下做法

你可能已经注意到,很少有 webpack 配置看起来很完全相同。这是因为 webpack 的配置文件,是导出一个对象的 JavaScript 文件。此对象,由 webpack 根据对象定义的属性进行解析。

七、模块(modules)

什么是 webpack 模块
对比 Node.js 模块,webpack 模块能够以各种方式表达它们的依赖关系,几个例子如下:

支持的模块类型
webpack 通过 loader 可以支持各种语言和预处理器编写模块。 webpack 社区已经为各种流行语言和语言处理器构建了 loader,包括:

总的来说,webpack 提供了可定制的、强大和丰富的 API,允许任何技术栈使用 webpack,保持了在你的开发、测试和生成流程中无侵入性(non-opinionated)。

八、模块解析(module resolution)

使用 enhanced-resolve,webpack 能够解析三种文件路径:
绝对路径

import "/home/me/file";
import "C:\\Users\\me\\file";

相对路径

import "../src/file1";
import "./file2";

模块路径

import "module";
import "module/lib/file";

如果路径指向一个文件

如果路径指向一个文件夹,则采取以下步骤找到具有正确扩展名的正确文件:

九、构建目标(targets)

因为服务器和浏览器代码都可以用 JavaScript 编写,所以 webpack 提供了多种构建目标(target),你可以在你的 webpack 配置中设置。
要设置 target 属性,只需要在你的 webpack 配置中设置 target 的值。

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

在上面例子中,使用 node webpack 会编译为用于「类 Node.js」环境(使用 Node.js 的 require ,而不是使用任意内置模块(如 fs 或 path)来加载 chunk)。

多个 Target

尽管 webpack 不支持向 target 传入多个字符串,你可以通过打包两份分离的配置来创建同构的库:

var path = require('path');
var serverConfig = {
  target: 'node',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'lib.node.js'
  }
  //…
};
var clientConfig = {
  target: 'web', // <=== 默认是 'web',可省略
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'lib.js'
  }
  //…
};
module.exports = [ serverConfig, clientConfig ];

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

十、模块热替换(hot module replacement)

模块热替换(HMR - Hot Module Replacement)功能会在应用程序运行过程中替换、添加或删除模块而无需重新加载整个页面。

主要是通过以下几种方式,来显著加快开发速度:

在应用程序中

通过以下步骤,可以做到在应用程序中置换(swap in and out)模块:

你可以设置 HMR,以使此进程自动触发更新,或者你可以选择要求在用户交互时进行更新。

在编译器中

除了普通资源,编译器(compiler)需要发出 "update",以允许更新之前的版本到新的版本。"update" 由两部分组成:

manifest 包括新的编译 hash 和所有的待更新 chunk 目录。每个更新 chunk 都含有对应于此 chunk 的全部更新模块(或一个 flag 用于表明此模块要被移除)的代码。

在模块中
上一篇 下一篇

猜你喜欢

热点阅读