[译 + 补充] Webpack 2 入门

在今时本日,webpack 已经成为前端开发异常重要的东西之一。本质上它是一个 Javascript 模组封装东西,但透过 loaders 和 plugins 它也能够转换封装其他前端的资源档像是 HTML,CSS,以至是图片等,让我们能够掌握程式发出 HTTP 请求的数量(编译结果的档案数量)。我们能够运用偏好的体式格局去撰写这些资源档像是 Jade, Sass, ES6 等等。同时也让我们能够轻易的运用来自 npm 的套件。

这篇文章目标读者是那些刚接触 webpack 的新手。内容将会包括设定,模组的运用,loaders,plugins,code splitting(分拆程式码),热替换(Hot module replacement)。

每过一阵子,从新学习 webpack 就会有些新的发现 – 废话。

为了完成文章中的练习您须要些前置作业:安装 Nodejs(译者运用 v6.9.2),假如您还么安装那么这边有篇完全运用 nvm 安装的教学

设定

让我们开始来运用 npm 初始化专案与安装 webpack。

$ mkdir webpack-demo
$ cd webpack-demo
$ npm init -y
$ npm i webpack@2 -D
$ npm view webpack version
# 2.2.1
$ mkdir src
$ touch index.html src/app.js webpack.config.js

上面这些档案的大要说明:

  • index.html – 首页,载入运用编译好的 Javascript 档案。

  • src/ 目录 – 许多开发者会把 Source Code 的目录定名为 src 但这并不强迫。

  • webpack.config.js – 设定 webpack 行为的设定档,这边我们能够先大要相识一下 webpack 的行为能够靠设定档或许指令的参数调整,而 webpack.config.js 是预设的设定档名称。

  • src/app.js – 这是我们程式的 Entry point。

接着编辑我们刚产出的这些档案

  • index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Hello webpack 2</title>
</head>
<body>
  <div id="root"></div>
  <script src="dist/bundle.js"></script>
</body>
</html>
  • src/app.js

const root = document.querySelector('#root')
root.innerHTML = `<p>Hello webpack 2</p>`
  • webpack.config.js

const path = require('path')
const config = {
  /**
   * webpack 执行环境,即 webpack 载入档案时相对路径的根目录环境
   * 预设(没有设定时)为执行指令(webpack)地点的那个目录
   *
   * 【其他】
   * 假设自身新增一个 build/build.js 档案,运用载入 webpack 的作法
   *
   * 比方范例:https://github.com/andyyou/webpack-context-prove/blob/master/build/build.js#L14
   *
   * 在差别目录执行:
   * > node build/build.js (in root/ folder)
   * > node build.js (in build/ folder)
   * 预设 context 会分别为 root/ 和 root/build/
   */
  context: path.join(__dirname, 'src'),
  /**
   * Entry point
   * 因为设定了 context 所以不须要加上 src/ 了
   */
  entry: './app.js',
  /**
   * 输前途径与档名
   */
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  /**
   * loaders 对应运用规则
   */
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          {
            /* webpack 2.x 移除了省略 -loader 的写法 */
            loader: 'babel-loader',
            options: {
              presets: [
                /* Loose mode and No native modules(Tree Shaking) */
                ['es2015', { modules: false, loose: false }]
              ]
            }
          }
        ]
      }
    ]
  }
}

module.exports = config

上面这些是常见的基础设定,它告诉 webpack 怎样编译我们的原始码,进入点是 src/app.js 输出的档案则放在 dist/bundle.js
一切的 .js 档案都会运用 Bable 从 ES2015 被编译成 ES5。

Babel 从 6.13.0 之后供应额外的参数 loose 和 modules
loose: 供应 loose 编译形式,该形式启动下 Babel 会尽能够产生较精简的 ES5 程式码,预设 false 会尽能够产出靠近 ES2015 规范的程式码。
modules: 转换 ES2015 module 的语法(import)为别的类型,预设为 true 转换为 commonjs。

为了要能够执行我们须要安装 babel-corebabel-loaderbabel-preset-es2015。上面还有一个值得注重的处所就是 {modules: false} 关闭这个设定是为了供应 Tree Shaking 的特征 – 移除没有运用到的 exports 来缩小编译的档案大小。

$ npm i babel-core babel-loader babel-preset-es2015 -D

最后我们在 package.json 补上 scripts 的部份。

"scripts": {
  "start": "webpack --watch",
  "build": "webpack -p"
}

到这步我们就能够运用 npm start 来执行 webpack,到场参数 –watch 会让 webpack 进入监视形式,当发现档案有异动时就会马上从新编译我们的原始码。在 console 画面会输出类似下面的讯息来示知我们 bundle 已经被竖立了。同时有个小小的重点那就是我们可已观察编译后的档案大小。

Webpack is watching the files…

Hash: f4fadf78c49f43d8a078
Version: webpack 2.2.1
Time: 1342ms
    Asset    Size  Chunks             Chunk Names
bundle.js  2.6 kB       0  [emitted]  main
   [0] ./app.js 87 bytes {0} [built]

在专案目录下执行 open index.html 能够观察住手现在为止的结果。

开启 dist/bundle.js 看看 webpack 编译的结果,上半部是 webpack 处理模组载入的程式码,最下面则是我们的模组。
到这您能够不觉得有什么特别的,不过一旦我们开始运用 ES2015 来开发并将程式模组化,那么 webpack 就能够替我们处理后续的事情让我们的原始码编译成能够在浏览器执行的版本。

接着,我们能够透过 Ctrl + C 来住手 webpack,换成执行 npm run build 能够编译产品形式的 bundle(压缩)。
您能够注重到档案大小从 2.6kB 变成 587 bytes,再次观察 dist/bundle.js 会发现程式码已经被 Uglify 了。

至此我们初始化了专案并对 webpack 设定有了基础的相识。

模组

webpack 自身晓得该怎样处理载入各种花样的 Javascript 模组,比较值得注重的有两个:

  • ES2015 import

  • CommonJS require()

我们运用 lodash 来试验看看

$ npm i lodash -S
  • src/app.js

import {groupBy} from 'lodash/collection'
const people = [{
  manager: 'Jen',
  name: 'Bob'
}, {
  manager: 'Jen',
  name: 'Sue'
}, {
  manager: 'Bob',
  name: 'Shirley'
}, {
  manager: 'Bob',
  name: 'Terrence'
}]
const managerGroups = groupBy(people, 'manager')

const root = document.querySelector('#root')
root.innerHTML = `<pre>${JSON.stringify(managerGroups, null, 2)}</pre>`

执行 npm start 然后在浏览器从新载入 index.html 应该要看到我们透过 lodash 区分群组的结果。
接着让我们把 people 的资料搬移到 src/people.js

  • src/people.js

const people = [{
  manager: 'Jen',
  name: 'Bob'
}, {
  manager: 'Jen',
  name: 'Sue'
}, {
  manager: 'Bob',
  name: 'Shirley'
}, {
  manager: 'Bob',
  name: 'Terrence'
}]

export default people

src/app.js 运用 import 载入 people.js

import {groupBy} from 'lodash/collection'
import people from './people'
const managerGroups = groupBy(people, 'manager')

const root = document.querySelector('#root')
root.innerHTML = `<pre>${JSON.stringify(managerGroups, null, 2)}</pre>`

注重:不运用相对路径的比方 lodash/collection 模组将会从 /node_modules 载入,我们自定义的模组平常运用相对路径。

汇入模组时的 path 分红 函式库 node_modules 相对路径 绝对路径

  • 函式库:什么都不加,单纯 library name

  • 相对路径:./ 开头

  • 绝对路径:/ 开头

第二小节我们示范了模组的运用,也就是我们能够把程式模组化再运用 webpack 来处理汇入运用的部份。

Loaders

上面我们已经运用了 babel-loader,它是众多 loader 中的一个,服从就是把 ES2015 转成 ES5。而 loaders 的服从就是告诉 webpack 该怎样处理汇入的档案,平常是 Javascript 但 webpack 不限于处理 Javascript,其他资源档像是 Sass,图片等也都能够处理,只需供应对应的 loader。
同时 loader 也能够串连运用,概念上类似于 Linux 中的 pipe,A Loader 处理完之后把结果交给 B Loader 继续转换,以此类推。
最好的示范范例就是汇入 Sass 的流程,下面就让我们来看看。

Sass

我们的目标是要把 Sass 编译封装到我们的 bundle 中(Javascript)。这个转换过程须要一些 loaders 和函式库:

$ npm i css-loader style-loader sass-loader node-sass -D

为处理 .scss 类型的档案到场新的编译规则

module: {
  rules: [
    // {...},
    {
      test: /\.scss$/,
      /**
       * use 属性是用来套用,串接多个 loaders。
       * v2 为了相容的要素保存 loaders 属性,loaders 为 use 的别名,
       * 尽能够的运用 use 替代 loaders
       */
      use: [
        'style-loader',
        'css-loader',
        'sass-loader'
      ]
    }
    // {...}
  ]
}

每当我们修正了 webpack.config.js 我们就必须重启。 Ctrl + C -> npm start

设定 loaders 的阵列实际上会反过来一一执行:

  1. sass-loader – 编译 Sass 成为 CSS

  2. css-loader – 剖析 CSS 转换成 Javascript 同时剖析相依的资源

  3. style-loader – 输出 CSS 到 document 的 <style> 元素内

我们能够想成像下面这样调用 function

styleLoader(cssLoader(sassLoader('source')))

让我们来到场 Sass

  • src/style.scss

$bg-color: #2B3A43;
pre {
  padding: 15px;
  background: $bg-color;
  color: #DEDEDE;
}

现在我们能够在 app.js 汇入 scss 了。

import './style.scss'

重载 index.html 我们应该能够看到样式已经套用了。

CSS in JS

上一步我们完成了从 JS 中把 Sass 当作一个模组载入。

打开 dist/bundle.js 搜寻 pre {,我们看到 Sass 已经被编译为字串并存为一个模组。当我们汇入该模组时 style-loader 会把该字串嵌入 <style> 标签中。

为什么我们要这么作呢?

这边我们不想探讨太多这个议题,不过的确有些来由让我们这么作:

  • 追念我们在运用 jQuery 套件或 Javascript 元件时,假如这些元件包括些资源档像是 HTML,CSS,图片,SVG 等等,平常这时候我们就须要把这档案搬到对应的目录下,又或许我们有洁癖愿望图档等放在我们定义的目录下,这时我们就须要去修正路径。当悉数都封装在 Javascript 时我们在组织时就轻易许多。

  • 轻易移除不须要的程式码 – 当 Javascript 元件不在被运用时, CSS 等资源档内容也会一并被移除。

  • CSS Module – 随着 CSS 样式越来越多,定名经常轻易冲突,透过 CSS Module 的体式格局能够对特定元件或模组套用其专用(local)的样式,只要该模组能够套用样式,这样一来也相对轻易维护。

  • 减少 HTTP request 的数量。

图片

最后我们要在介绍一个常碰到的需求 – 图片。我们将要运用 url-loader 来处理图片的载入。
在标准的 HTML 文件中图片须要透过 <img> 标签或 CSS 的 background-image 来载入。运用 webpack 我们能够优化图片并根据档案大小分别处理。像是把比较小的图片转成 base64 字串存在 Javascript 中。这么作浏览器能够预先载入,而且不会发出额外的 HTTP 请求。

npm i file-loader url-loader -D

当然我们记住了,每当我们须要一个 loader 来帮我们处理某类型的档案时,我们除了安装该 loader 外,还须要设定 rules

rules: [
  // ...
  {
    test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
    use: [
      {
        loader: 'url-loader',
        options: {
          limit: 10000 /* 小于 10kB 的图片转成 base64 */
        }
      }
    ]
  }
]

让我们下载张图片并将其放在 src/

$ curl http://i.imgur.com/5Hk42Ct.png --output src/code.png

接着在 app.js 中运用下面范例载入

  • src/app.js

import imageURL from './code.png'
const img = document.createElement('img')
img.src = imageURL
img.style = 'background: #2B3A4F; padding: 15px;'
img.width = 32
document.body.appendChild(img)

检查 HTML 该图片元素,我们看到会以下图片的来源被转换成 base64 了。

<img src="data:image/png;base64,iVBORw0KGgoAAAANSU..." style="background: rgb(43, 58, 79) none repeat scroll 0% 0%; padding: 15px;" width="32">

不只是在 Javascript 载入的图片,我们之前提到 css-loader 同时也会剖析相依的资源,然则要处理图片 css-loader 也是须要 url-loader 来帮忙。我们能够从 css-loader 的文件 options 一节得知

  • src/style.scss

pre {
  background: $bg-color url('code.png') no-repeat center center;
}

也会被编译成

pre {
  background: $bg-color url('data:image/png;base64,iVBORw0KG...') no-repeat center center;
}

从模组到静态资源

现在您应该邃晓 loaders 是怎样协助我们编译各式各样的档案,这也是 webpack 2 官方文件首页 出现图片所要表达的。

《[译 + 补充] Webpack 2 入门》

透过 Javascript 的 Entry point 进入点,webpack 就会邃晓我们须要那些模组以及各种类型的档案该怎样处理。

心法:组织好专案架构后,安装 webpack,设定的基础是 entry,output 以及想编译哪些类型的档案,对应安装相关 loaders 接着设定 rules。

Plugins

开始讲 plugins 之前,其实我们已经看过一个 webpack 内建的 plugin。它就是当我们执行 webpack -p 时运用的 UglifyJsPlugin。

简单说,loaders 的任务是针对单一档案协助转换,而 plugins 的任务则针对转换后的程式码片断作处理。

通用程式码

commons-chunk-plugin 是另一个内建的中心套件,能够将多个 Entry point 中共用模组的部份抽出来独立成一个模组。
到这边我们都只要单一个 Entry point 然后只输出一个 bundle。在实务上您能够会须要多个进入点来切割 bundle,比方:我们自身开发的部份归纳在 app.js,其他外部的函式库归纳在 vendor.js

又或许假设我们的网站有两个服从上须要切割的部份 – 平常运用者 app.js 和管理者 admin.js。这么一来我们就能够像下面这样处理:

const path = require('path')
const webpack = require('webpack')

const extractCommons = new webpack.optimize.CommonsChunkPlugin({
  name: 'commons',
  filename: 'commons.js'
})

const config = {
  context: path.join(__dirname, 'src'),
  entry: {
    app: './app.js',
    admin: './admin.js'
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].bundle.js'
  },
  // ...
  plugins: [
    extractCommons
  ]
}

module.exports = config

注重到 output.filename 部份我们在前面加上了 [name],同时 entry 也从字串换成物件花样,物件 key 的名称会对应到 [name],也就是照上面的设定会产生 app.bundle.jsadmin.bundle.js 两只档案。

commons-chunk-plugin 则会把这两个 entry point 中共用的模组抽出来产生第三只档案 commons.js

我们先来看看范例:

  • src/app.js

import './style.scss'
import {groupBy} from 'lodash/collection'
import people from './people'

const managerGroups = groupBy(people, 'manager')

const root = document.querySelector('#root')
root.innerHTML = `<pre>${JSON.stringify(managerGroups, null, 2)}</pre>`
  • src/admin.js

import people from './people'
const root = document.querySelector('#root')
root.innerHTML = `<p>There are ${people.length} people.</p>`

再次执行 npm start 就会看到 webpack 产生了 3 只档案

  • app.bundle.js 包括了 style 和 lodash/collection

  • admin.bundle.js 没有其他额外的模组

  • commons.js 包括 people 模组

然后调整 HTML 的部份:

  • index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Hello webpack 2</title>
  <style>
  html, body {
    padding: 0;
    margin: 0;
  }
  </style>
</head>
<body>
  <div id="root"></div>
  <script src="dist/commons.js"></script>
  <script src="dist/app.bundle.js"></script>
</body>
</html>
  • admin.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Hello webpack 2 - Admin</title>
  <style>
  html, body {
    padding: 0;
    margin: 0;
  }
  </style>
</head>
<body>
  <div id="root"></div>
  <script src="dist/commons.js"></script>
  <script src="dist/admin.bundle.js"></script>
</body>
</html>

当我们分别造访两个页面的时候,commons.js 也能够因为前一次被 cache 了而加快了网页载入的速率。

《[译 + 补充] Webpack 2 入门》
《[译 + 补充] Webpack 2 入门》

输出 CSS 档案

前面我们把 CSS 也当作模组汇入并打包进 Javascript,但实务上我们想要让浏览器非同步载入和平行处理 CSS 所以我们须要输出独立的 CSS 档案。

这时我们就要别的一个异常热门的 plugin – extract-text-webpack-plugin 它能够将模组汇出成档案。

下面我们将改写 .scss rule 的部份,将编译好的 CSS 汇出成档案,而不是放在 Javascript。

# extract-text-webpack-plugin 2 正处于 rc 阶段
# 我们能够透过下面的指令检察一切的版本
$ npm show extract-text-webpack-plugin versions

# 安装
$ npm i extract-text-webpack-plugin@2.0.0-rc.3 -D

接着修正 webpack.config.js

const path = require('path')
const webpack = require('webpack')

const extractCommons = new webpack.optimize.CommonsChunkPlugin({
  name: 'commons',
  filename: 'commons.js'
})
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const extractCSS = new ExtractTextPlugin('[name].bundle.css')

const config = {
  context: path.join(__dirname, 'src'),
  entry: {
    app: './app.js',
    admin: './admin.js'
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].bundle.js'
  },
  module: {
    rules: [
      // ...
      {
        test: /\.scss$/,
        loader: extractCSS.extract(['css-loader', 'sass-loader'])
        /*
        use: [
          'style-loader',
          'css-loader',
          'sass-loader'
        ]
        */
      }
    ]
  },
  plugins: [
    extractCommons,
    extractCSS
  ]
}

module.exports = config

重启 webpack 您应该能够看到 webpack 汇出了 app.bundle.css,于是我们就能够在 HTML 中补上连结。每一个 entry 内汇入的 Sass 都会被抽出来成一只独立的档案。由于 admin 没有汇入 Sass 所以没有输出。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Hello webpack 2</title>
  <style>
  html, body {
    padding: 0;
    margin: 0;
  }
  </style>
  <link rel="stylesheet" href="dist/app.bundle.css">
</head>
<body>
  <div id="root"></div>
  <script src="dist/commons.js"></script>
  <script src="dist/app.bundle.js"></script>
</body>
</html>

分拆原始码

我们已经看了一些分拆程式码的体式格局:

  • 手动竖立多个 Entry point

  • 运用 commons-chunk-plugin 分拆出共用模组的部份

  • 运用 extract-text-webpack-plugin

别的一个分拆的体式格局是运用 System.importrequire.ensure。透过调用这些要领设定,我们能够划分程式码让它们在须要的时候才在执行时期(runtime)载入,而不是一口气悉数载入。这样能够有用的改良载入所形成的效能问题。System.import 运用 module 名称作为参数,接着回传一个 Promise。require.ensure 则是传入相依套件的列表, callback,和一个可选的参数来设定该程式片断的名称。

System.import 是 ES2015 模组载入的 API

假如您的程式中某部份具有大批相依函式库,且程式的其他处所不须要。这种情况恰好就适合将其拆分出来。看看下面的范例,我们的 dashboard.js 须要 d3,但能够见得的别的处所不须要 d3。

$ npm i d3 -S
  • src/dashboard.js

import * as d3 from 'd3'

console.log('Loaded', d3)

export const draw = () => {
  console.log('Draw!')
}

接着在 app.js 的最下方我们模拟晚一点载入(须要的时候才载入)

function gotoDashboard () {
  System.import('./dashboard')
    .then(function (dashboard) {
      dashboard.draw()
    })
    .catch(function (err) {
      console.log('Chunk loading failed')
    })
}

setTimeout(gotoDashboard, 5000)

因为我们运用的是 System.import('./dashboard') 这样的相对路径,在线上的情况下会变成 http://example.com/dashboard.js 这样的路径是错误的。所以须要加上 output.publicPath 的设定,这样才会是 http://example.com/dist/dashboard.js

output: {
  path: path.join(__dirname, 'dist'),
  publicPath: '/dist/',
  filename: '[name].bundle.js'
}

重启 webpack 会发现 console 有一个新鲜的 0.bundle.js

Hash: e96d4e3ab03b79a320aa
Version: webpack 2.2.1
Time: 4030ms
          Asset       Size  Chunks                    Chunk Names
    0.bundle.js     452 kB       0  [emitted]  [big]
  app.bundle.js     184 kB       1  [emitted]         app
admin.bundle.js  461 bytes       2  [emitted]         admin
     commons.js    5.91 kB       3  [emitted]         commons
 app.bundle.css    1.31 kB       1  [emitted]         app

webpack 用了较为凸起的颜色显示 [big] 让我们去注重它。

这个 0.bundle.js 将会在须要的时候发出 JSONP 的请求,这个时候假如我们继续直接读取档案的体式格局是拿不到资料的。
暂时我们能够在专案目录下运用 python 供应的简易伺服器(因为 Linux,OSX 内定都有 python 我们不须要在作其他安装)。

$ python -m SimpleHTTPServer

浏览 http://localhost:8000,5 秒后我们应该能够看到一个 GET 请求 /dist/0.bundle.js 同时 console 显示 Loaded 载入完成。

Webpack Dev Server

Live reload 的出现,大大的改良了我们的开发体验也替开发者们节省了许多的时间。简单的说就是当档案发生变动时浏览器会自动从新载入页面。
只须要安装并运用 webpack-dev-server 这个开发伺服器我们就能够轻松获得这个服从。

$ npm i webpack-dev-server@2 -D

接着我们须要修正 package.json scripts start 的部份:

"scripts": {
  "start": "webpack-dev-server --inline",
  "build": "webpack -p"
},

执行 npm start 就能够透过 http://localhost:8080 来浏览网页。

现在,只需我们修正 src 目录下的档案,比方:people.jsstyle.scss 就能够看到浏览器马上更新结果。

热替换(Hot Module Replacement)

假如您对于 Live reload 印象深入的话,那么 HMR 能够将令你觉得惊讶。

假如您已经在开发 SPA (Signle Page Application),您应该已经遭受过了这种恼人的情况 – 在你的开发过程经常因为要测试某元件而反复操纵一些流程。什么意义?假如我们正在开发付款流程的页面,分别有 4 个步骤,我们的元件在第 3 步,于是每当我们一修正,一切状态因为重载的关系回到预设,然后我们就只好反复执行步骤 1, 2。

Hot Module Replacement 就是为了挽救我们脱离这个回圈而出现了。

我们抱负的开发流程应该是:每当我们修正我们的模组,然后应该只需编译该模组,在不革新浏览器,不影响其他模组的情况下把新的程式码换上去,当我们须要 reset 状态时在重载页面。大致上这就是 HMR 的服从。

我们只须要到场一个参数 --hot 就能够启用这个服从:

"scripts": {
  "start": "webpack-dev-server --inline --hot",
  "build": "webpack -p"
}

为了让我们的模组也增援 HMR 我们须要在 app.js 的最上面补上下面这段程式码,好让 webpack 晓得我们模组的边界以及更新底下相依的元件。

if (module.hot) {
  module.hot.accept()
}

注重:webpack-dev-server --hot 会把 module.hot 设为 true 而且只要在开发形式才增援。在 production 形式下 module.hot 会是 false,相关的程式码不会出现在 bundle 中。

到场 NamedModulesPlugin 到 webpack.config.js 的 plugins 阵列,云云一来我们在浏览器的 console 就能够看出是哪个档案更新。

plugins: [
  // ...
  new webpack.NamedModulesPlugin()
]

最后,我们到场 <input> 到 HTML ,从新执行 npm start 并在页面的输入框输入一些字,编辑 people.js 中的人名,存档。我们能够观察到 HMR 的行为,的确不是整个页面革新。

Hot Reloading CSS

修正 style.scss<pre> 的背景色,我们注重到 HMR 并没有对应更新

pre {
  background: red;
}

当我们运用 style-loader 时 HMR 是会更新的,我们不须要作其他设定。不过因为我们运用了 extract-text-webpack-plugin 把 CSS 独立出去成为档案,所以也就不增援 HMR。

HTTP/2

运用 webpack 这类的封装东西一个重要的好处就是能够掌握最终资源档被请求的数量。在过去几年这是最好的实作体式格局,不过 HTTP/2 的出现,整合成单档的体式格局不再是唯一,疏散成许多小档案在 HTTP/2 中是相对好的作法。

不过 webpack 的作者 Tobias Koppers 写了篇文章阐述纵然在 HTTP/2 的情况下,封装东西仍有其重要性。连结

资源

    原文作者:andyyu0920
    原文地址: https://segmentfault.com/a/1190000008390333
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞