1. 程式人生 > >Webpack 4 教程:從0配置到生產模式

Webpack 4 教程:從0配置到生產模式

webpack 4 問世了!除了大幅度的效能提升,而且增加了零配置的預設設定。 在這裡插入圖片描述

目錄

webpack 4 ,零配置的模組打包工具

webpack 是一個強力和有著很多獨特功能的工具,但是他的一大痛點在於他的配置檔案

如果是大中型專案我新增配置檔案沒什麼大問題,有時候也是必須的。但是有時候就隨便弄個專案來玩玩,還要新增配置檔案,嗯,很不友好。

這也是 Parcel 之所以受歡迎的原因

現在的好訊息是 webpack 4 預設也不需要配置檔案了!撒花撒花~ ?

webpack 4:零配置開始

建立一個目錄然後進入

mkdir webpack-4-quickstart && cd
$_

初始化 package.json

npm init -y

安裝 webpack4:

npm i webpack --save-dev

還需要安裝另外一個包:webpack-cli

npm i webpack-cli --save-dev

然後開啟 package.json 新增構建指令碼:

"scripts": {
  "build": "webpack"
}

試著執行

npm run build

然後我們看到

ERROR in Entry module not found: Error: Can't resolve './src' in '~/webpack-4-quickstart'

OJBK! 沒有找到入口檔案。

簡要來說:webpack 需要這個入口檔案來開始 js 程式碼的打包。

在以前的版本里 webpack 的入口檔案需要在配置檔案 webpack.config.js 裡指定。

但是現在不需要了,它會預設選擇 ./src/index.js 這個檔案。

測試這個新特性很容易,建立一個 ./src/index.js:

console.log(`I'm a silly entry point`)

重新試試構建:

npm run build

你會在 ~/webpack-4-quickstart/dist/main.js 得到你打包後的檔案。

咦?等一下。都不需要指定輸出檔案嗎?是的。

在 webpack 4 中是不需要指定入口和輸出檔案。

webpack 的真正本領是程式碼拆分。但是相信我,有一個零配置的工具可以讓你更加高效。

所以這就是第一個新特性:他會把 ./src/index.js 預設為入口檔案,把打包後的檔案放在 ./dist/main.js

下一章後我們能看到另一個有用的特性:生產和開發模式。

Webpack 4: 生產和開發模式

在專案中整兩份配置檔案是很正常的事了。

一個典型的例子:

  • 一個開發用的配置檔案,用來定義 webpack 的 dev server 和其他東西
  • 一個生產環境用的配置檔案,用來定義 UglifyJSPlugin,sourcemap 和其他東西。

但是在 webpack4 中你能夠不寫一行配置。

咋這麼流弊呢?

webpack 4 介紹了生產( production) 和開發( development) 兩種模式。

實際上如果你關注過 npm run build 的輸出資訊你會看到這個警告:

在這裡插入圖片描述

The ‘mode’ option has not been set. Set ‘mode’ option to ‘development’ or ‘production’ to enable defaults for this environment.

這是什麼意思?我們看看。

開啟 package.json 檔案新增如下指令碼

"scripts": {
  "dev": "webpack --mode development",
  "build": "webpack --mode production"
}

現在執行:

npm run dev

檢視 ./dist/main.js 檔案。你看到了什麼?嘿嘿,嗯,他沒有被壓縮!

現在這樣:

npm run build

現在再看,你看到什麼?是不是壓縮了!

是的!

生產模式開啟了一系列額外的優化。包括 minification, scope hoisting, tree-shaking 等, 點贊 ?。

另外開發模式為了優化速度,就沒有做壓縮了。

所以這是第二個新特性:生產和開發模式。

在 webpack4 你不需要一行配置,只需要一個 --mode 選項。

webpack 4:覆蓋預設的入口/出口檔案

我喜歡 webpack4 的零配置,但是,如果我要覆蓋預設的入口或者出口配置要怎麼做呢?

package.json 裡配置他們。

比如:

"scripts": {
  "dev": "webpack --mode development ./foo/src/js/index.js --output ./foo/main.js",
  "build": "webpack --mode production ./foo/src/js/index.js --output ./foo/main.js"
}

webpack 4:用 Babel 7 轉譯 ES6 的 js 程式碼

現在大家都習慣用 ES6 寫 Javascript。

但是不是所有瀏覽器都知道怎麼處理 ES6。我們需要做一些轉換。

這個轉換的步驟叫做 transpiling。transpiling 是指把 ES6 轉譯成瀏覽器能夠識別的程式碼。

webpack 本身並不知道如何去轉換,但是有 loaders。把他們想象成轉換器。

babel-loader 是 webpack 的一個 loader,可以把 ES6 以上的程式碼轉譯成 ES5。

為了使用這個 loader 我們需要去安裝一系列的依賴。特別是:

  • babel-core
  • babel-loader
  • babel-preset-env (for compiling Javascript ES6 code down to ES5)

先安了吧:

npm i babel-core babel-loader babel-preset-env --save-dev

下一步我們在專案目錄下建立一個 .babelrc 檔案用來配置 Babel。

{
  "presets": ["env"]
}

在這裡我們有兩個途徑去配置 babel-loader:

  • 用 webpack 的配置檔案
  • 在 npm 腳本里使用 --module-bind

擦,說好的零配置呢,這怎麼又跟我談配置,童話裡都是騙人的。

So,為什麼我們又要寫配置檔案了呢。

原來 webpack 4 的零配置指的是:

  • 入口檔案。預設是 ./src/index.js
  • 出口檔案。預設是 ./dist/main.js
  • 生產和開發模式(無需建立兩套配置檔案)

就這些了。對於 loaders 我們仍然需要使用配置檔案哦,微笑 ?。

作者就這件事問過 Sean(webpack 的核心開發者)。在 webpack 4 中 loaders 是否和 webpack 3 中沒有區別?有計劃對這些通用的 loaders 比如 babel-loader 提供零配置嗎?

他的回答是:

在未來的版本(v4 之後,可能是 4.x 或者 5.0),我們已經開始探索預設或附加系統如何幫助我們定義這一點。我們不想要的是:把一堆東西塞到核心程式碼裡去。我們需要的是:能夠支援擴充套件。

對於現在來說你仍必須依賴 webpack.config.js。

webpack 4:通過配置檔案使用 babel-loader

建立一個名叫 webpack.config.js 的檔案然後配置 loader:

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  }
}

沒有必要去指定入口檔案除非你想指定。

下一步開啟 ./src/index.js 然後寫一些 ES6 程式碼:

const arr = [1, 2, 3]
const iAmJavascriptES6 = () => console.log(...arr)
window.iAmJavascriptES6 = iAmJavascriptES6

最後打包:

npm run build

然後去 ./dist/main.js 看看轉換後的程式碼。

webpack 4:不通過配置檔案使用 babel-loader

還有一種使用 webpack loaders 的方法。

--module-bind 選項讓你從命令列指定 loaders。

這個選項並不是 webpack 4 獨有的。3 開始就有了。

你可以這樣在 package.json 中使用:

"scripts": {
    "dev": "webpack --mode development --module-bind js=babel-loader",
    "build": "webpack --mode production --module-bind js=babel-loader"
}

然後你就可以開始構建了。

我並不是很喜歡這種方法(不喜歡太長的 npm 指令碼),儘管如此它很有趣。

webpack 4:在 webpack 4 中配置 React

在這裡插入圖片描述

如果你已經安裝配置好了 babel 這會很簡單。

安裝 React:

npm i react react-dom --save-dev

新增 babel-preset-react:

npm i babel-preset-react --save-dev

.babelrc 裡配置 preset

{
  "presets": ["env", "react"]
}

這樣就可以了。

如 Conner Aiken 建議的你可以配置 babel-loader 也去載入 .jsx 檔案。這在你使用 jsx 副檔名的時候很有用。

開啟 webpack.config.js 然後這樣配置:

module.exports = {
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  }
}

測試是否搭好你可以在 ./src/App.js 裡建立一個 React 元件。

import React from 'react'
import ReactDOM from 'react-dom'
const App = () => {
  return (
    <div>
      <p>React here!</p>
    </div>
  )
}
export default App
ReactDOM.render(<App />, document.getElementById('app'))

然後在 ./src/index.js 中引入:

import App from './App'

重新構建試試

webpack 4:HTML 外掛

webpack 需要兩個額外的元件去處理 HTML:html-webpack-pluginhtml-loader

新增這兩個依賴:

npm i html-webpack-plugin html-loader --save-dev

然後更新 webpack 的配置

const HtmlWebPackPlugin = require('html-webpack-plugin')
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      },
      {
        test: /\.html$/,
        use: [
          {
            loader: 'html-loader',
            options: { minimize: true }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: './src/index.html',
      filename: './index.html'
    })
  ]
}

在 ./src/index.html 新建一個 HTML 檔案:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>webpack 4 quickstart</title>
</head>
<body>
    <div id="app">
    </div>
</body>
</html>

執行:

npm run build

檢視 ./dist 目錄。你會看到執行後的結果。

沒有必要在你的 HTML 檔案中引入你的 JavaScript:它會自動地注入進去。

在瀏覽器開啟 ./dist/index.html:你可以看到 React 元件執行起來了!

如你所見在處理 HTML 上並沒有什麼新變化。

webpack 4 目前仍然是一個針對 js 的模組的打包工具。

但是有這個想法,就是新增 HTML 作為一個模組(比如把 HTML 作為入口檔案)。

webpack 4: 提取 CSS 到檔案中

webpack 並不知道怎麼去提取 CSS 到檔案中。

在之前這都是交給 extract-text-webpack-plugin 完成的。

不幸的是這個外掛在 webpack 4 已經實在玩不動了。

Michael Ciniawsky 說:

維護 extract-text-webpack-plugin 是一個很大的負擔,而且這不是第一次因為這貨不給力,使得升級 webpack 的主版本都變得異常艱難。

這貨被拍死在沙灘後,mini-css-extract-plugin 是來替代它的。

提示:你得把 webpack 版本升級到 4.2.0,才能用這個外掛!

安裝它:

npm i mini-css-extract-plugin css-loader --save-dev

然後建立一個 CSS 檔案用來測試:

/* */
/* CREATE THIS FILE IN ./src/main.css */
/* */
body {
  line-height: 2;
}

配置 loader 和 plugin:

const HtmlWebPackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      },
      {
        test: /\.html$/,
        use: [
          {
            loader: 'html-loader',
            options: { minimize: true }
          }
        ]
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      }
    ]
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: './src/index.html',
      filename: './index.html'
    }),
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css'
    })
  ]
}

最後在入口檔案中引入 CSS:

// PATH OF THIS FILE: ./src/index.js
import style from './main.css'

構建:

npm run build

檢視 ./dist 目錄,你應該能看到 CSS 的結果!

重點回顧extract-text-webpack-plugin 在 webpack 4 中不能用了。請使用 mini-css-extract-plugin

webpack 4:webpack dev server

在你改變程式碼後執行 npm run dev?這不是個理想的做法。花幾分鐘去配置下 webpack 的開發服務。一旦配置了 webpack dev server 它會在瀏覽器中載入你的 app。

只要你改變了檔案,它會自動地重新整理瀏覽器的頁面。

安裝下面的包來搭建 webpack dev server

npm i webpack-dev-server --save-dev

然後開啟 package.json 調整指令碼:

"scripts": {
  "start": "webpack-dev-server --mode development --open",
  "build": "webpack --mode production"
}

儲存關閉。

現在執行:

npm run start

你就會看到 webpack dev server 在瀏覽器中載入你的應用了。

webpack dev server 非常適合用來開發。(而且它能使得的 React Dev Tools 在瀏覽器中正常的工作)