Webpack 4 教程 - 6. 加強開發體驗

咱們今天要涉及到把mode屬性設置爲development(時的情形)。這會讓webpack自動配置成更適合開發(時用)。此外,咱們也將涉及到webpack-dev-server和webpack-serve - 其包括了熱模塊替換(譯註:webpack-serve如今已不推薦使用,用好webpack-dev-server就夠了,詳見https://github.com/webpack-co...)。開始吧!javascript

Webpack 4教程: 一個開發服務器

加強開發體驗的一個前置步驟是以觀察模式運行webpack,試着以webpack --watch啓動,如今,每當你作了些修改,webpack就會重建你的項目且輸出相應的信息(譯註: 原文是」and outputs he code「,小小疑惑一下)。而Webpack-dev-server就更強大了,作得更多。(使用Webpack-dev-server時)輸出文件不是寫到磁盤的目標目錄中,而是在內存裏處理。構建以後,這些輸出啓動了一個本地服務器。css

運行webpack-dev-server

首先要安裝html

npm install webpack-dev-server

其次在package.json中添加腳本java

"scripts": {
    "build": "webpack",
    "start": "webpack-dev-sever"
}

如今啓動它,只需輸入 npm start(譯註:在前面的教程中,做者寫的啓動腳本的命令形如npm run build,實際上在較高版本的npm中,能夠省略這個run了)。你就會看到下面的信息:webpack

「wds」: Project is running at http://localhost:8080/

剩下的事情就只需你在瀏覽器中打開http://localhost:8080/了git

每當對代碼作了些修改,站點就會獲得更新(由於重建項目了啊),刷新頁面以後,你就會看到這些改變了的效果。github

熱模塊替換

爲了使開發體驗更佳,能夠使用熱模塊替換來避免老是手動刷新。好比,每當你改變了一些樣式,你無需重載整個應用來觀察改變的效果。web

注意,在教程4中咱們用到了MiniCssExtractPlugin這個插件,到寫這篇文章的時候爲止,MiniCssExtractPlugin還不支持熱模塊替換。更多信息請參考 GitHub issue。所以如今你在開發模式下還需繼續要用到style-loader這個加載器。(譯註:style-loader的做用就是把你的樣式插入到<style>標籤中,在開發模式下,輸出都是放在內存中,所以把css抽取出來仍是放在<style>標籤中,都無所謂了,不用考慮太多)

正規狀況下,webpack-dev-server也是經過同一個配置文件(即webpack.config.js)來運行。能在webpack.config.js中添加一個叫devServer的參數來設置附加的配置選項。咱們在其上啓用熱模塊替換。npm

devServer: {
    hot: true,
}

剩下最後一件事情就是將webpack.HotModuleReplacementPlugin寫到plugins屬性裏。json

// webpack.config.js

const webpack = require('webpack');

module.exports = {
    devServer: {
        hot: true
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin()
    ]
}
注意啓動webpack-dev-server時加上 -hot參數也會加載HotModuleReplacementPlugin插件。你要是不經意加載了兩次,可能會給你帶來一些麻煩。

如今工做於CSS中已經很是奏效了,但在javascript中,咱們還須要進一步。

index.js

import { divide } from "./divide";

console.log(`6 / 2 = ${divide(6,2)}`);

if(module.hot) {
    module.hot.accept();
}
// divider.js

export function divide(a, b) {
    return a/b;
}

運行module.hot.accept()將使得模塊可替換。這也會在它導出的模塊身上起效果。上面的代碼例子意味着在index.js中運行了accept(),則它導出的divide模塊也變成可替換的了。(譯註:咱們在一些開箱即用的框架中每每看到做者爲你配了一個相似dev-client.js的文件,這個文件的做用就是讓後面被它導出的模塊可以熱替換)。

函數module.hot.accept()能夠附加配置來運行,若是感興趣,請參閱 文檔

使用HotModuleReplacementPlugin插件時,若是在輸出文件名中用了chunkhash,會碰到問題。所以,最好HotModuleReplacementPlugin只用在開發服務器中(且不使用chunkhash)。

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const isDevServer = require.main.filename.includes('webpack-dev-server');
const plugins = [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
];
if(isDevServer) {
    plugins.push(new webpack.HotModuleReplacementPlugin());
}

module.exports = {
    output: {
        filename: isDevServer ? '[name].bundle.js' : '[name].[chunkhash].bundle.js',
        path: path.resolve(__dirname, 'dist'),
    },
    plugins,
    devServer: {
        hot: true
    }
}

webpack-serve

(譯註:由於webpack-serve官方已不推薦使用,咱們略過這一節的巴拉巴拉)

mode: 「development」

在前面的教程中,咱們已經涉及了mode爲production時的狀況。如今咱們來看看當其值爲development時,對咱們作了什麼。

DefinePlugin插件

就象前面所說的,這個插件建立全局常量編譯時解析。

更多細節講述請參閱教程5。

如今其值是 "process.env.NODE_ENV": JSON.stringify("development") :

module.exports = {
    mode: "development",
    // using mode: "development" attaches the following configuration:
    plugins: [
        new webpack.DefinePlugin({
            "process.env.NODE_ENV": JSON.stringify("development")
        }),
    ]
}

NamedModulesPlugin插件

這是在設置mode:"development"時另外一個默認加載的內置插件。在使用熱模塊替換時起做用。因爲NamedModulesPlugin咱們能看到替換模塊的相對路徑。

[WDS] App updated. Recompiling...
[WDS] App hot update...
[HMR] Checking for updates on the server...
[HMR] Updated modules:
[HMR]  - ./src/style.css
[HMR] App is up to date

不然,咱們只能看到用模塊id來表明某模塊了(好比./src/style.css)。

NamedChunksPlugin插件

NameChunksPlugin插件的做用與NamedModulesPlugin插件有點類似。有了NamedChunksPlugin插件,不但你的模塊有了名字,chunks也有了。 當在瀏覽器中運行應用時,你能在window.webpackJsonp屬性中找到它們。

NamedModulesPlugin和NamedChunksPlugin另一個優點是你無需使用模塊id(ids),ids在增刪依賴時可能會發生變化。由於ids或名字用在實際輸出的文件裏,即便你模塊的內容沒有變化,改變ids或名字也會改變文件的hash。因此使用NamedModulesPlugin和NamedChunksPlugin插件將幫助你更好的應付瀏覽器緩存機制。咱們比較一下輸出代碼。

// Without NamedModulesPlugin and NamedChunksPlugin

(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[2],{
  /***/ 6:
  (...) // divide.js module output code

  /***/ 7:
  (...) // substract.js module output code
]);
// Using NamedModulesPlugin and NamedChunksPlugin:

(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["utilities~main"],{
  /***/ "./src/utilities/divide.js":
  (...) // divide.js module output code

  /***/ "./src/utilities/substract.js":
  (...) // substract.js module output code
]);

devtool

除了加載了一些插件,設置mode: "development"(譯註:原文誤爲production)時還多作了一件事,它經過設置devtool屬性爲eval來啓用源碼映射(Source Maps)。

module.exports = {
    mode: "development",
    // using mode: "development" attaches the following configuration:
    devtool: "eval"
}

轉換,醜化,打包你的代碼會讓用戶(體驗)更爽,在這些措施以後,代碼變小了,執行變快了。然而調式這些代碼變困難了。所以,引入了源碼映射機制。它們映射輸出代碼到源文件,使得調式器用起來更簡單及能在源代碼中打斷點。咱們將在接下來的教程中深挖源碼映射,但若是你如今就想去定製,請查閱文檔

小結

Webpack是開發現代web應用強有力的工具。它不但優化你的產品代碼,也能經過定製的方式來提高開發體驗。這一次咱們涉及到了運行一個開發服務器和設置mode屬性爲development。咱們也學習瞭如何使用熱模塊替換。這些結合起來會大大幫助你更快更容易的開發應用。

相關文章
相關標籤/搜索