webpack概念

官网:http://www.css88.com/doc/webpack2/concepts/

webpack是js的模块打包器(module bundler)。

入口(Entry)

webpack将创建所有应用程序的依赖关系图标(dependency graph)。

入口起点(entry point):图表的起点。根上下文(contextual root)  app第一个启动文件

入口起点告诉webpack从哪里开始,遵循依赖图表打包文件。

webpack中使用webpack配置对象的entry属性定义入口。

单个入口(简写)语法

 

用法: entry: string | Array<string>

 webpack.config.js

1 module.exports = {
2   entry: './path/to/my/entry/file.js'
3 };
4 module.exports = config;

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

1 module.exports = {
2   entry: {
3       main: './path/to/my/entry/file.js'
4   }
5 };

向entry传入一个数组会发生什么?将创建多个入口。

对象语法

用法:entry: {[entryChunkName: string]: string | Array<string>} 

const config = {
  entry: {
    app: './src/app.js',   // 应用程序(app)
    vendors: './src/vendors.js'  // 公共库(vendor)
  }
};

 对象语法是应用程序中定义入口的最可扩展的方式。

可扩展的webpack配置:可重用并可与其他配置组合使用。用于将关注点从环境、构建目标、运行时中分离,然后用专门的工具(如 webpack-merge)将它们合并。

 

输出(Output)

所有的资源(assets)归拢在一起后,需要告诉webpack在哪里打包应用程序。

output属性,描述了如何处理归拢在一起的代码(bundled code)。

webpack.config.js

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  }
};

用法(Usage)

 将output设置为一个对象,包括以下两点:

1.编译文件的文件名(filename),推荐:main.js   ||   bundle.js   ||  index.js

2.output.path对应一个绝对路径(一次性打包的目录)。

webpack.config.js

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

选项(Options)

可以向output属性传入的值。

output.chuckFilename

非入口的 chunk(non-entry chunk) 的文件名,路径相对于 output.path 目录。

[id] 被 chunk 的 id 替换。

[name] 被 chunk 的 name 替换(或者,在 chunk 没有 name 时使用 id 替换)。

[hash] 被 compilation 生命周期的 hash 替换。

[chunkhash] 被 chunk 的 hash 替换。

output.crossOriginLoading

此选项启用跨域加载(cross-origin loading) chunk。

可选的值有:

false - 禁用跨域加载

"anonymous" - 启用跨域加载。当使用 anonymous 时,发送不带凭据(credential)的请求。

"use-credentials" - 启用跨域加载。发送带凭据(credential)的请求。

output.devtoolLineToLine

所有/指定模块启用行到行映射(line-to-line mapped)模式。

行到行映射模式使用一个简单的 SourceMap,即生成资源(generated source)的每一行都映射到原始资源(original source)的同一行。这是一个可做性能优化之处。

true 在所有模块启用(不推荐)

{test, include, exclude} 对象,对特定文件启用(类似于 module.loaders)。

默认值:false

output.filename

 指定硬盘每个输出文件的名称。

单个入口

{
  entry: './src/app.js',
  output: {
    filename: 'bundle.js'
    path: __dirname + 'build',
  }
}
// 写入到硬盘: ./build/bundle.js

 

多个入口

如配置创建多个“chunk”(例如使用多个入口起点或使用类似CommonsChunkPlugin(提取公共代码)的插件),为确保每个文件名都不重复,应使用以下替换方式:

[name] 被 chunk 的 name 替换。

[hash] 被 compilation 生命周期的 hash 替换。

[chunkhash] 被 chunk 的 hash 替换。

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

 

output.hotUpdateChunkFilename

热更新 chunk(Hot Update Chunk) 的文件名。在 output.path 目录中。

[id] 被 chunk 的 id 替换。

[hash] 被 compilation 生命周期的 hash 替换。(最后一个 hash 存储在记录中)

默认值:"[id].[hash].hot-update.js"

output.hotUpdateFunction

webpack 中用于异步加载(async load)热更新(hot update) chunk 的 JSONP 函数。

默认值:"webpackHotUpdate"

output.hotUpdateMainFilename

热更新主文件(hot update main file)的文件名。

[hash] 被 compilation 生命周期的 hash 替换。(最后一个 hash 存储在记录中)

默认值:"[hash].hot-update.json"

output.jsonpFunction

webpack 中用于异步加载(async loading) chunk 的 JSONP 函数。

较短的函数可能会减少文件大小。当单页有多个 webpack 实例时,请使用不同的标识符(identifier)。

默认值:"webpackJsonp"

output.library

如果设置此选项,会将 bundle 导出为 library。output.library 是 library 的名称。

如果你正在编写 library,并且需要将其发布为单独的文件,请使用此选项。

output.libraryTarget

library 的导出格式

"var" - 导出为一个变量:var Library = xxx(默认)

"this" - 导出为 this 的一个属性:this["Library"] = xxx

"commonjs" - 导出为 exports 的一个属性:exports["Library"] = xxx

"commonjs2" - 通过 module.exportsmodule.exports = xxx 导出

"amd" - 导出为 AMD(可选命名 - 通过 library 选项设置名称)

"umd" - 导出为 AMD,CommonJS2 或者导出为 root 的属性

默认值:"var"

如果 output.library 未设置,但是 output.libraryTarget 被设置为 var 以外的值,则「所导出对象」的每个属性都被复制到「对应的被导出对象」上(除了 amdcommonjs2 和 umd)。

output.path

导出目录为绝对路径(必选项)。

[hash] 被 compilation 生命周期的 hash 替换。

config.js

output: {
  path: "/home/proj/public/assets",
  publicPath: "/assets/"
}

 

index.html

<head>
  <link href="/assets/spinner.gif" />
</head> 

 

接下来是一个更复杂的例子,来说明对资源使用 CDN 和 hash。

config.js

output: {
  path: "/home/proj/cdn/assets/[hash]",
  publicPath: "http://cdn.example.com/assets/[hash]/"
}

 

注意:在编译时不知道最终输出文件的 publicPath 的情况下,publicPath 可以留空,并且在入口起点文件运行时动态设置。如果你在编译时不知道 publicPath,你可以先忽略它,并且在入口起点设置 __webpack_public_path__

 __webpack_public_path__ = myRuntimePublicPath
// 其他的应用程序入口

 

output.sourceMapFilename

JavaScript 文件的 SourceMap 的文件名。它们在 output.path 目录中。

[file] 被 JavaScript 文件的文件名替换。

[id] 被 chunk 的 id 替换。

[hash] 被 compilation 生命周期的 hash 替换。

默认值:"[file].map"

 

加载器(Loader)

webpack的目标是让webpack聚焦于项目中的所有资源(asset),而浏览器不需要关注这些(并不是资源都必须打包在一起)。webpack把每个文件(.css, .html, .scss, .jpg, etc.) 都作为模块处理。而且webpack只理解js

loader是对应用程序中资源文件进行转换。它们是(运行在Node.js中的)函数,可以将资源文件作为参数的来源,然后返回到新的资源文件。

webpack配置的目标:

1.识别(identity)被对应loader转换(transform)的文件

2. 进行过文件转换,可以将被转换的文件添加到依赖图表(最终添加到bundle中)(use属性)

webpack.config.js

const config = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      // 当遇到【在require() / import语句中被解析为'.js'或'.jsx'的路径】时,把它们添加并打包前,要先使用babel-loader转换
   {test: /\.(js | jsx)$/, use: 'babel-loader'}    
    ]
  }
};

module.exports = config;

 

在webpack配置中定义loader时,要定义在module.rules中,而不是rules。定义错时webpack会提出严重警告。

示例

可使用 loader 告诉 webpack 加载 CSS 文件,或者将 TypeScript 转为 JavaScript。

首先,安装相对应的 loader:

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

 

其次,配置 webpack.config.js,对每个 .css 文件使用 css-loader,对每个 .ts 文件使用 ts-loader

webpack.config.js

module.exports = {
  module: {
    rules: [
      {test: /\.css$/, use: ['css-loader'](loaders/css-loader)},
      {test: /\.ts$/, use: ['ts-loader']((https://github.com/TypeStrong/ts-loader))}
    ]
  }
};

注意,根据配置选项,下面的规范定义了同等的 loader 用法:

{test: /\.css$/, [loader](/configuration/module#rule-loader): 'css-loader'}
// or equivalently
{test: /\.css$/, [use](/configuration/module#rule-use): 'css-loader'}
// or equivalently
{test: /\.css$/, [use](/configuration/module#rule-use): {
  loader: 'css-loader',
  options: {}
}}

配置

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

  • 通过配置
  • 在 require 语句中显示使用
  • 通过 CLI

通过 webpack.config.js

module.rules 允许在 webpack 配置中指定几个 loader。

这是展示 loader 的一种简明的方式,并且有助于简洁代码,以及对每个相应的 loader 有一个完整的概述。

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

通过 require

可以在 require 语句(或 definerequire.ensure, 等语句)中指定 loader。使用 ! 将资源中的 loader 分开。分开的每个部分都相对于当前目录解析。

require('style-loader!css-loader?modules!./styles.css');

 

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

选项可以传递查询参数,就像在 web 中那样(?key=value&foo=bar)。也可以使用 JSON 对象(?{"key":"value","foo":"bar"})。

尽可能使用 module.rules,因为可以在源码中减少引用,并且更快调试和定位 loader,避免代码越来越糟。

通过 CLI

可选项,通过 CLI 使用 loader:

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

对 .jade 文件使用 jade-loader,对 .css 文件使用 style-loader 和 css-loader

Loader 特性

  • loader 支持链式传递。可对资源使用流水线(pipeline)。loader 链式地按照先后顺序进行编译。loader 链中的第一个 loader 返回值给下一个 loader。在最后一个 loader,返回 webpack 所预期的 JavaScript。
  • loader 可以是同步或异步函数。
  • loader 运行在 Node.js 中,可执行任何可能的操作。
  • loader 接收查询参数。用于 loader 间传递配置。
  • loader 也能够使用 options 对象进行配置。
  • 除了使用 package.json 常见的 main 属性,还可以将普通的 npm 模块导出为 loader,做法是在 package.json 里定义一个 loader 字段。
  • 插件(plugin)可以为 loader 带来更多特性。
  • loader 能够产生额外的任意文件。

loader 通过(loader)预处理函数,为 JavaScript 生态系统提供了更多有力功能。用户现在可以更加灵活的引入细粒度逻辑,例如压缩(compression)、打包(package)、语言翻译(language translation)和其他更多。

解析 Loader

loader 遵循标准的模块解析。多数情况下,loader 将从模块路径(通常是 npm installnode_modules)解析。

如何编写模块?

loader 模块需要导出为一个函数,并且使用 Node.js 兼容的 JavaScript 编写。通常使用 npm 管理 loader,也可以将 loader 模块作为应用程序中的文件。

按照约定,loader 通常被命名为 XXX-loader,其中 XXX 是上下文的名称,例如 json-loader

loader 的名称约定和优先搜索顺序,由 webpack 配置 API 中的 resolveLoader.moduleTemplates 定义。

 

插件(Plugins)

loader仅在每个文件的基础上执行转换,插件目的在于解决loader无法实现的事情。

插件(plugins)最常用(但不限)于在打包模块的“compilation”和“chunk”生命周期执行操作和自定义功能。

webpack的插件系统强大且可定制化。

在一个配置中,多次使用一个插件,用于不同的目的。

1.想使用一个插件,只需require()它,然后把它添加到plugins数组中。多数插件可以通过选项(option)自定义。

2.需要使用new来创建插件的实例,并且通过实例来调用插件。 

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');  // installed via npm(通过npm安装)
const webpack = require('webpack'); //to access built-in plugins(访问内置插件)
const path = require('path');

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

剖析

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

ConsoleLogOnBuildWebpackPlugin.js

function ConsoleLogOnBuildWebpackPlugin() {

};

ConsoleLogOnBuildWebpackPlugin.prototype.apply = function(compiler) {
  compiler.plugin('run', function(compiler, callback) {
    console.log("webpack 构建过程开始!!!");
    callback();
  });
};

 

 通过Function.prototype.apply方法可以把任意函数作为插件传递(this 将指向 compiler)。在配置中使用这样的方式来内联自定义插件。

用法

plugin 可以携带参数/选项,在 wepback 配置中,需向 plugins 属性传入 new 实例。

配置

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');  // installed via npm(通过npm安装)
const webpack = require('webpack'); //to access built-in plugins(访问内置插件)
const path = require('path');

const config = {
  entry: './path/to/my/entry/file.js';
  output: {
    filename: 'my-first-webpack.bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    loaders: [
      {
        test: /\.(js | jsx)$/, 
        loader: 'babel-loader'
       }
    ]
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin(),   // 优化js组件
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};
module.exports = config;            

 

配置(Configuration)

webpack 的配置文件是 JavaScript 文件导出的一个对象。此对象,由 webpack 根据对象定义的属性进行解析。

因为 webpack 配置是标准的 Node.js CommonJS 模块,可以如下:

  • 通过 require(...) 导入其他文件
  • 通过 require(...) 使用 npm 的工具函数
  • 使用 JavaScript 控制流表达式,例如 ?: 操作符
  • 对常用值使用常量或变量
  • 编写并执行函数来生成部分配置

不应该使用以下。从技术上讲可以这么做,但是并不推荐:

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

最简单的配置

webpack.config.js

var path = require('path');

module.exports = {
  entry: './foo.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'foo.bundle.js'
  }
};

多个 Target

webpack.config.js

var path = require('path');
var webpack = require('webpack');
var webpackMerge = require('webpack-merge');

var baseConfig = {
  target: 'async-node',
  entry: {
    entry: './entry.js'
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  },
  plugin: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'inline',
      filename: 'inline.js',
      minChunks: Infinity
    }),
    new webpack.optimize.AggressiveSplittingPlugin({
      minSize: 5000,
      maxSize: 10000
    }),
  ]
};

let targets = ['web', 'webworker', 'node', 'async-node', 'node-webkit', 'electron-main'].map((target) => {
  let base = webpackMerge(baseConfig, {
    target: target,
    output: {
      path: path.resolve(__dirname, 'diat/' + target),
      filename: '[name].' + target + '.js'
    }
  });
  return base;
});

module.exports = targets;

 

模块(Modules)

在模块化编程,开发者将程序分解成称为模块的离散功能块。

什么是 webpack 模块

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

  • ES2015 import 语句
  • CommonJS require() 语句
  • AMD define 和 require 语句
  • css/sass/less 文件中的 @import 语句。
  • 样式(url(...))或 HTML 文件(<img src=...>)中的图片链接(image url)

 webpack 1 需要特定的 loader 来转换 ES 2015 import,然而通过 webpack 2 可以开箱即用。

 

模块解析(Module Resolution)

解析器是一个通过绝对路径来帮助定位模块的库(library)。 一个模块可以作为另一个模块的依赖模块,然后被后者引用,如下:

import foo from 'path/to/module'
// or
require('path/to/module')

依赖模块可以来自应用程序代码或第三方库。解析器帮助 webpack 找到 bundle 中需要引入的模块代码,这些代码包含在 require/import 语句中。 当打包模块时,webpack 使用增强解析来解析文件路径

webpack 中的解析规则

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

绝对路径

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

 

已经有了文件的绝对路径,不需要进一步解析。

相对路径

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

 

出现 import 或 require 的资源文件的目录被认为是上下文目录(context directory)(当前处理文件的目录)。在 import/require 中给定的相对路径被追加到此上下文路径(context path),以生成模块的绝对路径(absolute path)。

模块路径

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

 

模块将在 resolve.modules 中指定的所有目录内搜索。 可以替换初始模块路径,此替换路径通过使用 resolve.alias 配置选项来创建一个别名。

一旦根据上述规则解析路径后,解析器(resolver)将检查路径是否指向文件或目录。如果路径指向一个文件:

  • 如果路径具有文件扩展名,则被直接将文件打包。
  • 否则,将使用 [resolve.extensions] 选项作为文件扩展名来解析,此选项告诉解析器在解析中能够接受哪些扩展名(例如 .js.jsx)。

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

  • 如果文件夹中包含 package.json 文件,则按照顺序查找 resolve.mainFields 配置选项中指定的字段。并且 package.json 中的第一个这样的字段确定文件路径。

webpack 根据构建目标(build target)为这些选项提供了合理的默认配置。

解析加载器(Resolving Loaders)

Loader 解析遵循与文件解析器指定的规则相同的规则。但是 resolveLoader 配置选项可以用来为 Loader 提供独立的解析规则。

缓存

每个文件系统访问都被缓存,以便更快触发对同一文件的多个并行或穿行请求。在观察模式下,只有修改过的文件会从缓存中摘出。如果关闭观察模式,在每次编译前清理缓存。

 

依赖图表(Dependency Graph)

任何时候一个文件依赖于另一个文件,webpack 把这个文件当作依赖处理。这使得 webpack 可以接收非代码资源(non-code asset)(例如图像或 web 字体),并且也能把它们作为依赖提供给应用。

webpack 从命令行或配置文件定义的一个模块列表,开始处理应用。 从这些入口点开始,webpack 递归地构建一个依赖图表,这个依赖图表包括应用所需的每个模块,然后将所有模块打包为少量的包(bundle) - 通常只有一个包 - 可由浏览器加载。

 对于 HTTP/1.1 客户端,打包应用会尤其强大,因为当浏览器发起一个新请求时,它能够最大限度地减少应用的等待次数。对于 HTTP/2,可以通过 webpack 使用代码拆分(Code Splitting)和打包实现最佳优化。

 

构建目标(Targets)

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

用法

要设置 target 属性,只需要在你的 webpack 配置中设置 target 的值。

webpack.config.js

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

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

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

多个 Target

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

webpack.config.js

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)

模块热替换功能会在应用程序运行过程中替换、添加或删除模块,而无需重新加载页面。在独立模块变更后,无需刷新整个页面,就可以更新这些模块,极大地加速了开发时间。

这一切是如何运行的?

站在 App 的角度

  1. app 代码要求 HMR runtime 检查更新。
  2. HMR runtime (异步)下载更新,然后通知 app 代码更新可用。
  3. app 代码要求 HMR runtime 应用更新。
  4. HMR runtime (异步)应用更新。

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

站在编译器(webpack) 的角度

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

  1. 待更新 manifest (JSON)
  2. 一个或多个待更新 chunk (JavaScript)

manifest 包括新的编译 hash 和所有的待更新 chunk 目录。

每个待更新 chunk 包括用于与所有被更新模块相对应 chunk 的代码(或一个 flag 用于表明模块要被移除)。

编译器确保模块 ID 和 chunk ID 在这些构建之间保持一致。通常将这些 ID 存储在内存中(例如,当使用 webpack-dev-server 时),但是也可能将它们存储在一个 JSON 文件中。

站在模块的角度

HMR 是可选功能,只会影响包含 HRM 代码的模块。举个例子,通过 style-loader 为 style 样式追加补丁。 为了运行追加补丁,style-loader 实现了 HMR 接口;当它通过 HRM 接收到更新,它会使用新的样式替换旧的样式。

类似的,当在一个模块中实现了 HMR 接口,你可以描述出当模块被更新后发生了什么。然而在多数情况下,不需要强制在每个模块中写入 HMR 代码。如果一个模块没有 HMR 处理函数,更新就会冒泡。这意味着一个简单的处理函数能够对整个模块树(complete module tree)进行处理。如果在这个模块树中,一个单独的模块被更新,那么整个模块树都会被重新加载(只会重新加载,不会迁移)。

站在 HMR Runtime 的角度 (Technical)

对于模块系统的 runtime,附加的代码被发送到 parents 和 children 跟踪模块。

在管理方面,runtime 支持两个方法 check 和 apply

check 发送 HTTP 请求来更新 manifest。如果请求失败,说明没有可用更新。如果请求成功,待更新 chunk 会和当前加载过的 chunk 进行比较。对每个加载过的 chunk,会下载相对应的待更新 chunk。当所有待更新 chunk 完成下载,就会准备切换到 ready 状态。

apply 方法将所有被更新模块标记为无效。对于每个无效模块,都需要在模块中有一个更新处理函数,或者在它的父级模块们中有更新处理函数。否则,无效标记冒泡,并将父级也标记为无效。每个冒泡继续直到到达应用程序入口起点,或者到达带有更新处理函数的模块(以最先到达为准)。如果它从入口起点开始冒泡,则此过程失败。

之后,所有无效模块都被(通过 dispose 处理函数)处理和解除加载。然后更新当前 hash,并且调用所有 "accept" 处理函数。runtime 切换回闲置状态,一切照常继续。

能使用 HMR 做什么?

可以在开发过程中将 HMR 作为 LiveReload 的替代。webpack-dev-server 支持热模式,在试图重新加载整个页面之前,热模式会尝试使用 HMR 来更新。查看如何实现在 React 项目中使用 HRM 为例。

一些 loader 已经生成可热更新的模块。例如,style-loader 能够置换出页面的样式表。对于这样的模块,不需要做任何特殊处理。

 

posted @ 2017-08-16 16:07  tong24  阅读(432)  评论(0编辑  收藏  举报