Webpack 開發(fā)環(huán)境

2023-05-17 15:40 更新

如果你一直跟隨之前的指南,應(yīng)該對(duì)一些 webpack 基礎(chǔ)知識(shí)有著很扎實(shí)的理解。在我們繼續(xù)之前,先來看看如何設(shè)置一個(gè)開發(fā)環(huán)境,使我們的開發(fā)體驗(yàn)變得更輕松一些。

在開始前,我們先將 mode 設(shè)置為 'development',并將 title 設(shè)置為 'Development'。

webpack.config.js

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

 module.exports = {
+  mode: 'development',
   entry: {
     index: './src/index.js',
     print: './src/print.js',
   },
   plugins: [
     new HtmlWebpackPlugin({
-      title: 'Output Management',
+      title: 'Development',
     }),
   ],
   output: {
     filename: '[name].bundle.js',
     path: path.resolve(__dirname, 'dist'),
     clean: true,
   },
 };

使用 source map

當(dāng) webpack 打包源代碼時(shí),可能會(huì)很難追蹤到 error(錯(cuò)誤) 和 warning(警告) 在源代碼中的原始位置。例如,如果將三個(gè)源文件(a.js, b.js 和 c.js)打包到一個(gè) bundle(bundle.js)中,而其中一個(gè)源文件包含一個(gè)錯(cuò)誤,那么堆棧跟蹤就會(huì)直接指向到 bundle.js。你可能需要準(zhǔn)確地知道錯(cuò)誤來自于哪個(gè)源文件,所以這種提示這通常不會(huì)提供太多幫助。

為了更容易地追蹤 error 和 warning,JavaScript 提供了 source maps 功能,可以將編譯后的代碼映射回原始源代碼。如果一個(gè)錯(cuò)誤來自于 b.js,source map 就會(huì)明確的告訴你。

source map 有許多 可用選項(xiàng),請(qǐng)務(wù)必仔細(xì)閱讀它們,以便可以根據(jù)需要進(jìn)行配置。

對(duì)于本指南,我們將使用 inline-source-map 選項(xiàng),這有助于解釋說明示例意圖(此配置僅用于示例,不要用于生產(chǎn)環(huán)境):

webpack.config.js

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

 module.exports = {
   mode: 'development',
   entry: {
     index: './src/index.js',
     print: './src/print.js',
   },
+  devtool: 'inline-source-map',
   plugins: [
     new HtmlWebpackPlugin({
       title: 'Development',
     }),
   ],
   output: {
     filename: '[name].bundle.js',
     path: path.resolve(__dirname, 'dist'),
     clean: true,
   },
 };

現(xiàn)在,讓我們來做一些調(diào)試,在 print.js 文件中生成一個(gè)錯(cuò)誤:

src/print.js

 export default function printMe() {
-  console.log('I get called from print.js!');
+  cosnole.log('I get called from print.js!');
 }

運(yùn)行 npm run build,編譯如下:

...
[webpack-cli] Compilation finished
asset index.bundle.js 1.38 MiB [emitted] (name: index)
asset print.bundle.js 6.25 KiB [emitted] (name: print)
asset index.html 272 bytes [emitted]
runtime modules 1.9 KiB 9 modules
cacheable modules 530 KiB
  ./src/index.js 406 bytes [built] [code generated]
  ./src/print.js 83 bytes [built] [code generated]
  ./node_modules/lodash/lodash.js 530 KiB [built] [code generated]
webpack 5.4.0 compiled successfully in 706 ms

現(xiàn)在,在瀏覽器中打開生成的 index.html 文件,點(diǎn)擊按鈕,并且在控制臺(tái)查看顯示的錯(cuò)誤。錯(cuò)誤應(yīng)該如下:

Uncaught ReferenceError: cosnole is not defined
   at HTMLButtonElement.printMe (print.js:2)

我們可以看到,此錯(cuò)誤包含有發(fā)生錯(cuò)誤的文件(print.js)和行號(hào)(2)的引用。這是非常有幫助的,因?yàn)楝F(xiàn)在我們可以確切地知道,所要解決問題的位置。

選擇一個(gè)開發(fā)工具

在每次編譯代碼時(shí),手動(dòng)運(yùn)行 npm run build 會(huì)顯得很麻煩。

webpack 提供幾種可選方式,幫助你在代碼發(fā)生變化后自動(dòng)編譯代碼:

  1. webpack's Watch Mode
  2. webpack-dev-server
  3. webpack-dev-middleware

多數(shù)場景中,你可能需要使用 webpack-dev-server,但是不妨探討一下以上的所有選項(xiàng)。

使用 watch mode(觀察模式)

你可以指示 webpack "watch" 依賴圖中所有文件的更改。如果其中一個(gè)文件被更新,代碼將被重新編譯,所以你不必再去手動(dòng)運(yùn)行整個(gè)構(gòu)建。

我們添加一個(gè)用于啟動(dòng) webpack watch mode 的 npm scripts:

package.json

 {
   "name": "webpack-demo",
   "version": "1.0.0",
   "description": "",
   "private": true,
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1",
+    "watch": "webpack --watch",
     "build": "webpack"
   },
   "keywords": [],
   "author": "",
   "license": "ISC",
   "devDependencies": {
     "html-webpack-plugin": "^4.5.0",
     "webpack": "^5.4.0",
     "webpack-cli": "^4.2.0"
   },
   "dependencies": {
     "lodash": "^4.17.20"
   }
 }

現(xiàn)在,你可以在命令行中運(yùn)行 npm run watch,然后就會(huì)看到 webpack 是如何編譯代碼。 然而,你會(huì)發(fā)現(xiàn)并沒有退出命令行。這是因?yàn)榇?script 當(dāng)前還在 watch 你的文件。

現(xiàn)在,webpack 觀察文件的同時(shí),先移除我們之前加入的錯(cuò)誤:

src/print.js

 export default function printMe() {
-  cosnole.log('I get called from print.js!');
+  console.log('I get called from print.js!');
 }

現(xiàn)在,保存文件并檢查 terminal(終端) 窗口。應(yīng)該可以看到 webpack 自動(dòng)地重新編譯修改后的模塊!

唯一的缺點(diǎn)是,為了看到修改后的實(shí)際效果,你需要刷新瀏覽器。如果能夠自動(dòng)刷新瀏覽器就更好了,因此接下來我們會(huì)嘗試通過 webpack-dev-server 實(shí)現(xiàn)此功能。

使用 webpack-dev-server

webpack-dev-server 為你提供了一個(gè)基本的 web server,并且具有 live reloading(實(shí)時(shí)重新加載) 功能。設(shè)置如下:

npm install --save-dev webpack-dev-server

修改配置文件,告知 dev server,從什么位置查找文件:

webpack.config.js

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

 module.exports = {
   mode: 'development',
   entry: {
     index: './src/index.js',
     print: './src/print.js',
   },
   devtool: 'inline-source-map',
+  devServer: {
+    static: './dist',
+  },
   plugins: [
     new HtmlWebpackPlugin({
       title: 'Development',
     }),
   ],
   output: {
     filename: '[name].bundle.js',
     path: path.resolve(__dirname, 'dist'),
     clean: true,
   },
+  optimization: {
+    runtimeChunk: 'single',
+  },
 };

以上配置告知 webpack-dev-server,將 dist 目錄下的文件 serve 到 localhost:8080 下。(譯注:serve,將資源作為 server 的可訪問文件)

我們添加一個(gè)可以直接運(yùn)行 dev server 的 script:

package.json

 {
   "name": "webpack-demo",
   "version": "1.0.0",
   "description": "",
   "private": true,
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1",
     "watch": "webpack --watch",
+    "start": "webpack serve --open",
     "build": "webpack"
   },
   "keywords": [],
   "author": "",
   "license": "ISC",
   "devDependencies": {
     "html-webpack-plugin": "^4.5.0",
     "webpack": "^5.4.0",
     "webpack-cli": "^4.2.0",
     "webpack-dev-server": "^3.11.0"
   },
   "dependencies": {
     "lodash": "^4.17.20"
   }
 }

現(xiàn)在,在命令行中運(yùn)行 npm start,我們會(huì)看到瀏覽器自動(dòng)加載頁面。如果你更改任何源文件并保存它們,web server 將在編譯代碼后自動(dòng)重新加載。試試看!

webpack-dev-server 具有許多可配置的選項(xiàng)。關(guān)于其他更多配置,請(qǐng)查看 配置文檔。

使用 webpack-dev-middleware

webpack-dev-middleware 是一個(gè)封裝器(wrapper),它可以把 webpack 處理過的文件發(fā)送到一個(gè) server。webpack-dev-server 在內(nèi)部使用了它,然而它也可以作為一個(gè)單獨(dú)的 package 來使用,以便根據(jù)需求進(jìn)行更多自定義設(shè)置。下面是一個(gè) webpack-dev-middleware 配合 express server 的示例。

首先,安裝 express 和 webpack-dev-middleware:

npm install --save-dev express webpack-dev-middleware

現(xiàn)在,我們需要調(diào)整 webpack 配置文件,以確保 middleware(中間件) 功能能夠正確啟用:

webpack.config.js

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

 module.exports = {
   mode: 'development',
   entry: {
     index: './src/index.js',
     print: './src/print.js',
   },
   devtool: 'inline-source-map',
   devServer: {
     static: './dist',
   },
   plugins: [
     new HtmlWebpackPlugin({
       title: 'Development',
     }),
   ],
   output: {
     filename: '[name].bundle.js',
     path: path.resolve(__dirname, 'dist'),
     clean: true,
+    publicPath: '/',
   },
 };

我們將會(huì)在 server 腳本使用 publicPath,以確保文件資源能夠正確地 serve 在 http://localhost:3000 下,稍后我們會(huì)指定 port number(端口號(hào))。接下來是設(shè)置自定義 express server:

project

  webpack-demo
  |- package.json
  |- package-lock.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);

// 告知 express 使用 webpack-dev-middleware,
// 以及將 webpack.config.js 配置文件作為基礎(chǔ)配置。
app.use(
  webpackDevMiddleware(compiler, {
    publicPath: config.output.publicPath,
  })
);

// 將文件 serve 到 port 3000。
app.listen(3000, function () {
  console.log('Example app listening on port 3000!\n');
});

現(xiàn)在,添加一個(gè) npm script,以使我們更方便地運(yùn)行 server:

package.json

 {
   "name": "webpack-demo",
   "version": "1.0.0",
   "description": "",
   "private": true,
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1",
     "watch": "webpack --watch",
     "start": "webpack serve --open",
+    "server": "node server.js",
     "build": "webpack"
   },
   "keywords": [],
   "author": "",
   "license": "ISC",
   "devDependencies": {
     "express": "^4.17.1",
     "html-webpack-plugin": "^4.5.0",
     "webpack": "^5.4.0",
     "webpack-cli": "^4.2.0",
     "webpack-dev-middleware": "^4.0.2",
     "webpack-dev-server": "^3.11.0"
   },
   "dependencies": {
     "lodash": "^4.17.20"
   }
 }

現(xiàn)在,在 terminal(終端) 中執(zhí)行 npm run server,將會(huì)有類似如下信息輸出:

Example app listening on port 3000!
...
<i> [webpack-dev-middleware] asset index.bundle.js 1.38 MiB [emitted] (name: index)
<i> asset print.bundle.js 6.25 KiB [emitted] (name: print)
<i> asset index.html 274 bytes [emitted]
<i> runtime modules 1.9 KiB 9 modules
<i> cacheable modules 530 KiB
<i>   ./src/index.js 406 bytes [built] [code generated]
<i>   ./src/print.js 83 bytes [built] [code generated]
<i>   ./node_modules/lodash/lodash.js 530 KiB [built] [code generated]
<i> webpack 5.4.0 compiled successfully in 709 ms
<i> [webpack-dev-middleware] Compiled successfully.
<i> [webpack-dev-middleware] Compiling...
<i> [webpack-dev-middleware] assets by status 1.38 MiB [cached] 2 assets
<i> cached modules 530 KiB (javascript) 1.9 KiB (runtime) [cached] 12 modules
<i> webpack 5.4.0 compiled successfully in 19 ms
<i> [webpack-dev-middleware] Compiled successfully.

現(xiàn)在,打開瀏覽器,訪問 http://localhost:3000。應(yīng)該看到 webpack 應(yīng)用程序已經(jīng)運(yùn)行!

調(diào)整文本編輯器

使用自動(dòng)編譯代碼時(shí),可能會(huì)在保存文件時(shí)遇到一些問題。某些編輯器具有 "safe write(安全寫入)" 功能,會(huì)影響重新編譯。

在一些常見的編輯器中禁用此功能,查看以下列表:

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

結(jié)論

現(xiàn)在,你已經(jīng)學(xué)會(huì)了如何自動(dòng)編譯代碼,并運(yùn)行一個(gè)簡單的 development server,查看下一個(gè)指南,其中將介紹代碼分割(Code Splitting)。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)