webpack 4 入門指南 系列五(開發(fā)篇)

本教程使用基于輸出管理教程的代碼示例。

  • 如果你一直遵循這些教程,那你應(yīng)該會對webpack的基本知識有充分的了解。在我們繼續(xù)之前,讓我們先來看看如何建立一個開發(fā)環(huán)境,讓我們的開發(fā)生活更輕松一些。

這篇教程中的所有工具都只適用于開發(fā)環(huán)境,請避免在生成環(huán)境使用。

使用源代碼映射(source map)

  • webpack打包源代碼時,想要在原來的位置追蹤錯誤和警告將會變得很困難。例如,如果你把這些文件 (a.js, b.js, 和c.js)打包進bundle(bundle.js),并且其中一個源文件有錯誤,堆棧蹤跡只會簡單的指向bundle.js。當你想確切的知道錯誤是從哪個源文件產(chǎn)生的時候,這種提示幾乎沒什么用。

  • 為了使追蹤錯誤和警告變得簡單點,JavaScript提供了source maps,將編譯后的代碼映射回源代碼。如果錯誤來源于b.jssource map會明確的告訴你。

  • source map有很多可用的選項,請確保你的配置是能夠滿足你的需要的。

  • 對本教程來說, 將會使用 inline-source-map選項,這對于簡單說明目的很好(盡管不適用于生產(chǎn)環(huán)境):

webpack.config.js

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

  module.exports = {
    entry: {
      app: './src/index.js',
      print: './src/print.js'
    },
+   devtool: 'inline-source-map',
    plugins: [
      new CleanWebpackPlugin(['dist']),
      new HtmlWebpackPlugin({
        title: 'Development'
      })
    ],
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist')
    }
  };
  • 為了讓我們能夠調(diào)試代碼,我們在print.js創(chuàng)造一個錯誤:
  export default function printMe() {
-   console.log('I get called from print.js!');
+   cosnole.log('I get called from print.js!');
  }
  • 執(zhí)行構(gòu)建命令,可能會編譯成這樣:
Hash: 7bf68ca15f1f2690e2d1
Version: webpack 3.1.0
Time: 1224ms
          Asset       Size  Chunks                    Chunk Names
  app.bundle.js    1.44 MB    0, 1  [emitted]  [big]  app
print.bundle.js    6.43 kB       1  [emitted]         print
     index.html  248 bytes          [emitted]
   [0] ./src/print.js 84 bytes {0} {1} [built]
   [1] ./src/index.js 403 bytes {0} [built]
   [3] (webpack)/buildin/global.js 509 bytes {0} [built]
   [4] (webpack)/buildin/module.js 517 bytes {0} [built]
    + 1 hidden module
Child html-webpack-plugin for "index.html":
       [2] (webpack)/buildin/global.js 509 bytes {0} [built]
       [3] (webpack)/buildin/module.js 517 bytes {0} [built]
        + 2 hidden modules
  • 現(xiàn)在在瀏覽器打開產(chǎn)生的index.html文件。在點擊按鈕式查看控制臺就會發(fā)現(xiàn)錯誤。可能是這樣的錯誤:
 Uncaught ReferenceError: cosnole is not defined
    at HTMLButtonElement.printMe (print.js:2)
  • 我們看到包含一個引用指向文件(print.js)已經(jīng)錯誤發(fā)生的位置第2行。很好,現(xiàn)在我們知道要想解決這個問題該去哪了。

選擇開發(fā)工具

一些文本編輯器有“safe write”功能,可能影響接下來的工具。查看調(diào)整你的編輯器來解決這些問題。

  • 每當你想編譯代碼時,手動運行npm run build是很麻煩的。

  • webpack中有一組不同的選項可以在代碼發(fā)生改變時幫你自動編譯。

    • webpack 的Watch模式
    • webpack-dev-server
    • webpack-dev-middleware
  • 大多數(shù)情況下,你可能會使用webpack-dev-server,但是我們來探索下上面所有的選項吧。

使用 watch 模式

  • 你可以命令webpack“監(jiān)視”依賴關(guān)系圖中所有文件的改變。只要其中一個文件發(fā)生改變,該文件的代碼就會重新編譯,你就不用每次都手動全部構(gòu)建了。

  • 我們添加一個npm腳本來開啟webpackWatch模式:

  {
    "name": "development",
    "version": "1.0.0",
    "description": "",
    "main": "webpack.config.js",
    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
+     "watch": "webpack --watch",
      "build": "webpack"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
      "clean-webpack-plugin": "^0.1.16",
      "css-loader": "^0.28.4",
      "csv-loader": "^2.1.1",
      "file-loader": "^0.11.2",
      "html-webpack-plugin": "^2.29.0",
      "style-loader": "^0.18.2",
      "webpack": "^3.0.0",
      "xml-loader": "^1.2.1"
    }
  }
  • 命令行執(zhí)行npm run watch并查看webpack是如何編譯你的代碼的。你會看到執(zhí)行完該命令后并不會退出命令行,因為該腳本正在監(jiān)視你的文件。

  • 現(xiàn)在,在webpack監(jiān)視你的文件的情況下,我們來移除之前介紹的錯誤:

src/print.jg

  export default function printMe() {
-   cosnole.log('I get called from print.js!');
+   console.log('I get called from print.js!');
  }
  • 現(xiàn)在保存文件并檢查終端控制臺。你應(yīng)該看到webpack重新編譯了發(fā)生改變的模塊!

  • 這種方式的唯一缺點就是你不得不刷新瀏覽器才能看到改變。如果能自動刷新就更好了,讓我們試試webpack-dev-server,它就會自動刷新。

使用 webpack-dev-server

  • webpack-dev-server為你提供一個簡單的服務(wù)器并且能夠熱加載。我們來設(shè)置一下:
npm install --save-dev webpack-dev-server
  • 修改配置文件以告訴dev 服務(wù)器到哪里查找文件:

webpack.config.js

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

  module.exports = {
    entry: {
      app: './src/index.js',
      print: './src/print.js'
    },
    devtool: 'inline-source-map',
+   devServer: {
+     contentBase: './dist'
+   },
    plugins: [
      new CleanWebpackPlugin(['dist']),
      new HtmlWebpackPlugin({
        title: 'Development'
      })
    ],
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist')
    }
  };
  • 這將告訴webpack-dev-serverlocalhost:8080dist目錄提供文件。

  • 讓我們添加一個腳本以便輕松啟動dev 服務(wù)器

package.json

  {
    "name": "development",
    "version": "1.0.0",
    "description": "",
    "main": "webpack.config.js",
    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
      "watch": "webpack --watch",
+     "start": "webpack-dev-server --open",
      "build": "webpack"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
      "clean-webpack-plugin": "^0.1.16",
      "css-loader": "^0.28.4",
      "csv-loader": "^2.1.1",
      "file-loader": "^0.11.2",
      "html-webpack-plugin": "^2.29.0",
      "style-loader": "^0.18.2",
      "webpack": "^3.0.0",
      "xml-loader": "^1.2.1"
    }
  }
  • 現(xiàn)在我們從命令行執(zhí)行npm start命令,就會看到我們的瀏覽器會自動加載我們的頁面。現(xiàn)在如果你改變?nèi)魏卧创a并保存,web 服務(wù)器就會在代碼編譯后自動加載。試一下!

  • webpack-dev-server提供了很多配置項。可以查看文檔了解更多

現(xiàn)在你的服務(wù)已經(jīng)啟動了,你可能想嘗試下 模塊熱加載

使用 webpack-dev-middleware (中間件)

  • webpack-dev-middleware是一個包裝器,它將webpack處理的文件發(fā)送到服務(wù)器。這在webpack-dev-server內(nèi)部使用,但它可以作為單獨的包提供,以便在需要時允許更多自定義設(shè)置。我們將看一個將webpack-dev-middleware與express 服務(wù)器**相結(jié)合的示例。

  • 首先安裝expresswebpack-dev-middleware

npm install --save-dev express webpack-dev-middleware
  • 現(xiàn)在我們需要做一些調(diào)整以確保webpack-dev-middleware能夠正常運行:

webpack.config.js

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

  module.exports = {
    entry: {
      app: './src/index.js',
      print: './src/print.js'
    },
    devtool: 'inline-source-map',
    plugins: [
      new CleanWebpackPlugin(['dist']),
      new HtmlWebpackPlugin({
        title: 'Output Management'
      })
    ],
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist'),
+     publicPath: '/'
    }
  };
  • publicPath也將在我們服務(wù)器腳本中使用,以確保在http://localhost:3000(我么稍后將指定端口號)上正確提供文件。下一步是設(shè)置我們的自定義express 服務(wù)器

project

  webpack-demo
  |- package.json
  |- webpack.config.js
+ |- server.js
  |- /dist
  |- /src
    |- index.js
    |- print.js
  |- /node_modules

server.js

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(webpackDevMiddleware(compiler, {
  publicPath: config.output.publicPath
}));

// Serve the files on port 3000.
app.listen(3000, function () {
  console.log('Example app listening on port 3000!\n');
});
  • 現(xiàn)在添加npm 腳本以方便運行服務(wù)器:

package.json

  {
    "name": "development",
    "version": "1.0.0",
    "description": "",
    "main": "webpack.config.js",
    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
      "watch": "webpack --watch",
      "start": "webpack-dev-server --open",
+     "server": "node server.js",
      "build": "webpack"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
      "clean-webpack-plugin": "^0.1.16",
      "css-loader": "^0.28.4",
      "csv-loader": "^2.1.1",
      "express": "^4.15.3",
      "file-loader": "^0.11.2",
      "html-webpack-plugin": "^2.29.0",
      "style-loader": "^0.18.2",
      "webpack": "^3.0.0",
      "webpack-dev-middleware": "^1.12.0",
      "xml-loader": "^1.2.1"
    }
  }
  • 現(xiàn)在在控制臺執(zhí)行npm run server,可能會輸出如下內(nèi)容:
Example app listening on port 3000!
webpack built 27b137af6d9d8668c373 in 1198ms
Hash: 27b137af6d9d8668c373
Version: webpack 3.0.0
Time: 1198ms
          Asset       Size  Chunks                    Chunk Names
  app.bundle.js    1.44 MB    0, 1  [emitted]  [big]  app
print.bundle.js    6.57 kB       1  [emitted]         print
     index.html  306 bytes          [emitted]
   [0] ./src/print.js 116 bytes {0} {1} [built]
   [1] ./src/index.js 403 bytes {0} [built]
   [2] ./node_modules/lodash/lodash.js 540 kB {0} [built]
   [3] (webpack)/buildin/global.js 509 bytes {0} [built]
   [4] (webpack)/buildin/module.js 517 bytes {0} [built]
Child html-webpack-plugin for "index.html":
         Asset    Size  Chunks  Chunk Names
    index.html  544 kB       0
       [0] ./node_modules/html-webpack-plugin/lib/loader.js!./node_modules/html-webpack-plugin/default_index.ejs 538 bytes {0} [built]
       [1] ./node_modules/lodash/lodash.js 540 kB {0} [built]
       [2] (webpack)/buildin/global.js 509 bytes {0} [built]
       [3] (webpack)/buildin/module.js 517 bytes {0} [built]
webpack: Compiled successfully.
  • 現(xiàn)在啟動瀏覽器并轉(zhuǎn)到http://localhost:3000,應(yīng)該看到你的webpack 應(yīng)用程序運行和起作用了!

如果您想了解更多關(guān)于熱模塊替換工作的內(nèi)容,我們建議您閱讀模塊熱加載

調(diào)整你的編輯器

  • 當你使用自動編譯代碼時,你可能在保存文件時遇到問題。一些編輯器有一個“safe write”的特性,它可能會干擾重新編譯。

  • 在一些常見的編輯器中禁止該特性:

    • Sublime Text 3: 在用戶首選項添加**atomic_save: "false" **。
    • JetBrains IDEs (e.g. WebStorm): 取消 "Use safe write": Preferences > Appearance & Behavior > System Settings
    • Vim: 設(shè)置添加:set backupcopy=yes

總結(jié)

  • 既然你已經(jīng)學會了自動編譯代碼已經(jīng)啟動一個簡單的開發(fā)服務(wù)器,你可以查看下一個教程 模塊熱加載.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容