摘要:我們先假設(shè)設(shè)置為從安裝然后就可以執(zhí)行的命令了上面的命令會自動打開你的瀏覽器并指定到修改一下你的文件并保存。比如,類似與解析等都是共通的功能,需要放在基礎(chǔ)配置文件里面然后使用來合并特定環(huán)境變量下指定的配置文件。
動態(tài)模塊替換(Hot Module Repalcement -React)原文發(fā)布與抹橋的博客-【翻譯向】webpack2 指南(中)
就像之前 理念頁面 中解析的細(xì)節(jié)那樣,動態(tài)模塊替換(HMR)會在應(yīng)用運(yùn)行時動態(tài)的替換、添加或者刪除模塊而不用重新刷新頁面。 HMR 非常有用,當(dāng)應(yīng)用只有一個狀態(tài)樹(single state tree)時。
下面介紹的方法描述中使用了 Babel 和 React ,但這并不是使用 HRM 所必須的工具。
項(xiàng)目配置這里會指導(dǎo)你如何用 Babel, React 和 PostCss 一起使用 HMR 去演示一個項(xiàng)目。為了能夠跟著下面走下去,需要把這些依賴添加到 package.json 中去。
為了使用 HMR,你需要如下這些依賴:
npm install --save-dev babel@6.5.2 babel-core@6.13.2 babel-loader@6.2.4 babel-preset-es2015@6.13.2 babel-preset-react@6.11.1 babel-preset-stage-2@6.13.0 css-loader@0.23.1 postcss-loader@0.9.1 react-hot-loader@3.0.0-beta.6 style-loader@0.13.1 webpack@2.1.0-beta.25 webpack-dev-server@2.1.0-beta.0
同時,為了達(dá)到我們演示的目的,還需要:
npm install --save react@15.3.0 react-dom@15.3.0Babel Config
.babelrc 文件應(yīng)該如下:
{ "presets": [ ["es2015", {"modules": false}], // webpack understands the native import syntax, and uses it for tree shaking "stage-2", // Specifies what level of language features to activate. // Stage 2 is "draft", 4 is finished, 0 is strawman. // See https://tc39.github.io/process-document/ "react" // Transpile React components to JavaScript ], "plugins": [ "react-hot-loader/babel" // Enables React code to work with HMR. ] }Webpack Config
const { resolve } = require("path"); const webpack = require("webpack"); module.exports = { entry: [ "react-hot-loader/patch", // activate HMR for React "webpack-dev-server/client?http://localhost:8080", // bundle the client for webpack-dev-server // and connect to the provided endpoint "webpack/hot/only-dev-server", // bundle the client for hot reloading // only- means to only hot reload for successful updates "./index.js" // the entry point of our app ], output: { filename: "bundle.js", // the output bundle path: resolve(__dirname, "dist"), publicPath: "/" // necessary for HMR to know where to load the hot update chunks }, context: resolve(__dirname, "src"), devtool: "inline-source-map", devServer: { hot: true, // enable HMR on the server contentBase: resolve(__dirname, "dist"), // match the output path publicPath: "/" // match the output `publicPath` }, module: { rules: [ { test: /.js$/, use: [ "babel-loader", ], exclude: /node_modules/ }, { test: /.css$/, use: [ "style-loader", "css-loader?modules", "postcss-loader", ], }, ], }, plugins: [ new webpack.HotModuleReplacementPlugin(), // enable HMR globally new webpack.NamedModulesPlugin(), // prints more readable module names in the browser console on HMR updates ], };
上面有很多配置,但不是所有都和 HMR 有關(guān)??梢酝ㄟ^查閱 webpack-dev-server options 和concept pages 來加深理解。
我們基礎(chǔ)設(shè)想是這樣的,你的 JavaScript 入口文件在 ./src/index.js 且你使用 CSS Module 來編寫樣式文件。
配置文件中需要重點(diǎn)關(guān)注的是 devServer 和 entry key. HotModueReplacementPlugin 同樣需要被包含在 plugins key 中。
為了達(dá)到目的,我們引入了兩個模塊:
react-hot-loader 添加到了入口中, 是為了能夠使 React 支持 HMR
為了更好的理解 HMR 每次更新的時候做了哪些事情,我們添加了 NamedModulePlugin
Code// ./src/index.js import React from "react"; import ReactDOM from "react-dom"; import { AppContainer } from "react-hot-loader"; // AppContainer is a necessary wrapper component for HMR import App from "./components/App"; const render = (Component) => { ReactDOM.render(, document.getElementById("root") ); }; render(App); // Hot Module Replacement API if (module.hot) { module.hot.accept("./components/App", () => { const NewApp = require("./components/App").default render(NewApp) }); }
// ./src/components/App.js import React from "react"; import styles from "./App.css"; const App = () => (); export default App;Hello,
.app { text-size-adjust: none; font-family: helvetica, arial, sans-serif; line-height: 200%; padding: 6px 20px 30px; }
一個需要特別注意的是 module 的引用:
Webpack 會暴露出 module.hot 給我們的代碼,當(dāng)我們設(shè)置 devServer: { hot: true } 時;
這樣我們可以使用 module.hot 來給特定的資源棄用 HMR (這里是 App.js). 這里有一個非常重要的 API module.hot.accept ,用來決定如何處理這些特定的依賴。
需要注意的是,webpack2 內(nèi)建支持 ES2015 模塊語法,你不需要在 module.hot.accept 中重新引用跟組件。為了達(dá)到這個目的,需要在 .babelrc 配置 Babel ES2015 的預(yù)先設(shè)置:
["es2015", {"modules": false}]
就像我們在之前 Babel Config 中配置的那樣。需要注意,禁用 Babel 的模塊功能 不僅僅是為了啟用 HMR。如果你不關(guān)掉這個配置,那么你會碰到需要問題。
如果你在 webpack2 的配置文件中使用 ES6 模塊,并且你按照 #3 修改了 .babelrc,那么你需要使用 require 語法來創(chuàng)建兩個 .babelrc 文件:
一個放在根目錄下面并配置為 "presets: ["es2015"]"
一個放在 webpack 要編譯的文件夾下,比如在這個例子中,就是 src/
所以在這個案例中,module.hot.accept 會執(zhí)行 render 方法無論 src/compoents/App.js 或者其它的依賴文件變化的時候 ——這意味著當(dāng) App.css 被引入到 App.js 中以后,即使是 App.css 被修改,
render 方法同樣會被執(zhí)行。
Index.html入口頁面需要被放在頁面 dist 下面,webpack-dev-server 的運(yùn)行需要這個文件。
Package.jsonExample Index
最后,我們需要啟動 webpack-dev-server 來打包我們的代碼并且看看 HMR 是如何工作的。我們可以使用如下的 package.json 入口:
{ "scripts" : { "start" : "webpack-dev-server" } }
執(zhí)行 npm start, 打開瀏覽器輸入 http://localhost:8080, 應(yīng)該可以看到下面這些項(xiàng)展示在 console.log中:
dev-server.js:49[HMR] Waiting for update signal from WDS… only-dev-server.js:74[HMR] Waiting for update signal from WDS… client?c7c8:24 [WDS] Hot Module Replacement enabled.
然后編輯并且修改 App.js 文件,你會在 console.log 中看到類似如下的日志:
[WDS] App updated. Recompiling… client?c7c8:91 [WDS] App hot update… dev-server.js:45 [HMR] Checking for updates on the server… log-apply-result.js:20 [HMR] Updated modules: log-apply-result.js:22 [HMR] - ./components/App.js dev-server.js:27 [HMR] App is up to date.
注意 HMR 指出了更新模塊的路徑。這是因?yàn)槲覀兪褂昧?NamedModulesPlugin.
開發(fā)環(huán)境(Development)這個章節(jié)介紹在開發(fā)過程中可以使用的一些工具。
需要注意,不能在生產(chǎn)環(huán)境使用
Source Map當(dāng) JS 發(fā)生異常的時候,我們需要指導(dǎo)是哪一個文件的哪一行出錯了。但是當(dāng)文件都被 webpack 打包以后,找問題會變得很麻煩。
Source Map 就是為了解決這個問題的。它有很多不同的選項(xiàng),每一種都有的好處和不足。在一開始,我們使用:
devtool: "cheap-eval-source-map"選擇一個工具(Choosing a Tool)
Webpack 可被用于監(jiān)視模式(watch mode)。這種模式下, webpack 會監(jiān)視你的文件,當(dāng)它們有變動的時候就會重編譯。Webpack-dev-server 提供了一個很方便使用的開發(fā)環(huán)境的服務(wù),并且支持自動刷新功能。如果你已經(jīng)有了一個開發(fā)環(huán)境的服務(wù),并且希望能夠擁有更好的適應(yīng)性,那么 webpack-dev-middleware 可以被用作一個中間件來達(dá)到這個目的。
Webpack-dev-server 和 webpack-dev-middleware 實(shí)在內(nèi)存中進(jìn)行編譯的,這意味著打包后的代碼包并不會保存到本地磁盤中。這回使打包變得很快,同時不會產(chǎn)生很多臨時文件來污染你的本地文件系統(tǒng)。
大多數(shù)情況下,你都會想要去使用 webpack-dev-server, 因?yàn)樗褂闷饋砗芊奖?,而且提供了許多開箱即用的功能。
Webpack 監(jiān)視模式(wtach mode)Webpack 的監(jiān)視模式會檢測文件的變動。只要變動被檢測到,它就會重新進(jìn)行一次編譯。我們希望它的編譯過程能有一個很好的進(jìn)度展示。那么就執(zhí)行以下命令:
webpack --progress --watch
隨便修改一個文件然后保存,你就會看到重新編譯的過程。
監(jiān)視模式?jīng)]有考慮任何和服務(wù)有關(guān)的問題,所以你需要自己提供一個服務(wù)。一個簡單的服務(wù)就是 [server](https://github.com/tj/serve). 當(dāng)安裝好后(npm i server -g),在你打包后的文件目錄下運(yùn)行:
server
當(dāng)每次重新編譯后,你都需要手動的去刷新瀏覽器。
webpack-dev-serverwebpack-dev-server 提供一個支持自動刷新的服務(wù)。
首先,確認(rèn)你 index.html 頁面里面已經(jīng)引用了你的代碼包。我們先假設(shè) output.filename 設(shè)置為 bundle.js: