v

前端小智@大遷世界發表於2020-11-18

作者:Tania Rascia
譯者:前端小智
來源:taniarascia

最近開源了一個 Vue 元件,還不夠完善,歡迎大家來一起完善它,也希望大家能給個 star 支援一下,謝謝各位了。

github 地址:https://github.com/qq449245884/vue-okr-tree

webpack 對我來說曾經是一個怪物般存在一樣,因為它有太多太多的配置項,相反,使用像create-react-app腳手架可以很輕鬆建立專案,所以有一段時間內,我會盡量避免使用 webpack,因為它看起來既複雜又望而卻步 ?

如果你們不習慣從頭開始設定 webpack 來使用BabelTypeScriptSassReactVue,或者不知道為什麼要使用 webpack,那麼這篇文章是你的最佳選擇。就像所有的事情一樣,一旦你深入學習,你會發現它並不是那麼可怕,只有幾個主要的概念需要學習掌握。

如果你是從 webpack 4 升級到 webpack 5,這裡有一些注意事項:

  • webpack-dev-server命令現在換成webpack-serve
  • file-loaderraw-loaderurl-loader不是必需的,可以使用內建的Asset Modules
  • 節點 polyfill 不再可用,例如,如果遇到stream錯誤,則可以將stream-browserify包作為依賴項新增,並將{stream:'stream-browserify'}新增到webpack配置中的alias屬性。

什麼是 webpack?

現在,大多數網站不再只是單單的由原生JS+純HTML編寫的,還涉及一些瀏覽器無法理解的語言,如果專案大,檔案多,對應的體積就大。所以要壓縮檔案和翻譯成所有瀏覽器都能理解的東西,這就是webpack的用武之地。

webpack 可以看做是模組打包器:它做的事情是,分析你的專案結構,找到JavaScript模組以及其它的一些瀏覽器不能直接執行的擴充語言(Scss,TypeScript等),並將其打包為合適的格式以供瀏覽器使用。

對於開發,webpack 還提供了一個開發伺服器,它可以在我們儲存時動態地更新模組和樣式。vue createcreate-response-app本質上都依賴於 webpack。

webpac k可以做很多事情,本文只是幫助大家熟悉一些主要概念並進行一些手動的配置。

安裝

首先,建立一個目錄webpack-tutorial,相關命令如下:

mkdir webpack-tutorial
cd webpack-tutorial
npm init -y  // 建立預設的 package.json

安裝webpackwebpack-cli

npm i -D webpack webpack-cli

接著,建立目錄 src,並在其裡面建立 index.js,內容如下:

console.log('Interesting!')

基本配置

在專案的根目錄中建立一個webpack.config.js

Entry

entry是配置模組的入口,可抽象成輸入,Webpack 執行構建的第一步將從入口開始搜尋及遞迴解析出所有入口依賴的模組。

entry 配置是必填的,若不填則將導致 Webpack 報錯退出。這裡,我們將src/index.js做為入口點。

const path = require('path')

module.exports = {
  entry: {
    main: path.resolve(__dirname, './src/index.js'),
  },
}

Output

配置 output 選項可以控制 webpack 如何向硬碟寫入編譯檔案。注意,即使可以存在多個入口起點,但只指定一個輸出配置。這裡指定輸出的路徑為 ‘dist’:

module.exports = {
  /* ... */

  output: {
    path: path.resolve(__dirname, './dist'),
    filename: '[name].bundle.js',
  },
}

現在,我們具有構建捆綁包所需的最低配置。 在package.json中,我們可以建立一個執行webpack命令的構建指令碼。

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

現在可以執行它了:

npm run build

現在在 dist 目錄會生成一個 main.bundle.js 檔案

外掛

webpack有一個外掛介面,這使得它更加靈活。內部webpack程式碼和第三方擴充套件使用外掛,有一些主要的方法幾乎每個webpack專案都會用到。

HTML 模板檔案

目前,我們有一個隨機的bundle檔案,但它對我們還不是很有用。如果需要使用main.bundle.js,就要藉助 HTML頁面來載入這個 JS 包作為指令碼。我們希望HTML檔案自動引入這個生成 js 檔案,所以我們將使用html-webpack-plugin建立一個HTML模板。

安裝一下:

npm i -D html-webpack-plugin

src資料夾中建立一個template.html檔案,這裡,我們自定義一個title,內容如下:

src/template.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>

  <body>
    <div id="root"></div>
  </body>
</html>

建立配置的plugins屬性,然後將外掛,檔名新增到輸出(index.html),並連結到將基於該模板的模板檔案。

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

module.exports = {
  /* ... */

  plugins: [
    new HtmlWebpackPlugin({
      title: 'webpack Boilerplate',
      template: path.resolve(__dirname, './src/template.html'), // template file
      filename: 'index.html', // output file
    }),
  ],
}

現在再次執行構建,會看到dist資料夾現在包含一個index.html,裡面也自動引入了我們打包好的 js 檔案。用瀏覽器開啟 index.html,會在控制檯看到 Interesting!

接著,在index.js中我們動態插入一些 dom 元素到頁面中,內容如下:

// Create heading node
const heading = document.createElement('h1')
heading.textContent = 'Interesting!'

// Append heading node to the DOM
const app = document.querySelector('#root')
app.append(heading)

重新構建,在進入 dist 目錄下面,用 http-server 執行 html 檔案。

http-server

可以在頁面上看到,我們注入的 "Interesting!",還會注意到捆綁檔案已縮小。

注意:在安裝HtmlWebpackPlugin後,你會看到一個DeprecationWarning,因為外掛在升級到webpack 5後還沒有完全擺脫deprecation警告。

Clean

我們還需要設定clean-webpack-plugin,在每次構建後清除dist資料夾中的所有內容。 這對於確保不遺留任何舊資料很重要。

clean-webpack-plugin-刪除/清理構建資料夾

const path = require('path')

const HtmlWebpackPlugin = require('html-webpack-plugin')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')

module.exports = {
  /* ... */

  plugins: [
    /* ... */
    new CleanWebpackPlugin(),
  ],
}

Modules and Loaders

webpack 使用 loader 預處理一些載入的檔案,如 js 檔案、靜態資源(如影像和CSS樣式)和編譯器(如TypeScriptBabel)。webpack 5也有一些內建的資產載入器。

在我們的專案中,有一個HTML檔案,該檔案可以載入並引入一些 JS ,但實際上並沒有執行任何操作。 那麼這個webpack配置要做的主要事情是什麼?

  • 將 JS 編譯為瀏覽器可以理解的版本
  • 匯入樣式並將 SCSS 編譯為 CSS
  • 匯入影像和字型
  • (可選)設定React或Vue

Babel (JavaScript)

Babel是一個工具,可讓使用最新的 JS 語法。

建立一個規則來檢查專案中(node_modules之外)的任何.js檔案,並使用babel-loader進行轉換。 Babel 還有一些其他的依賴項:

  • babel-loader-使用 Babel 和 webpack 傳輸檔案。

  • @babel/core-將ES2015+ 轉換為向後相容的 JavaScript

  • @babel/preset-env-Babel 的智慧預設設定

  • @babel/plugin-proposal-class-properties-自定義 Babel 配置的示例(直接在類上使用屬性)

npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-env @babel/plugin-proposal-class-properties

webpack.config.js

module.exports = {
  /* ... */

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

如果是 TypeScript 專案,使用的是typescript-loader而不是babel-loader

現在Babel已經設定好了,但是我們的Babel外掛還沒有。可以在index.js中新增一些新的語法來證明它還不能正常工作。

// 建立沒有建構函式的類屬性
class Game {
  name = 'Violin Charades'
}
const myGame = new Game()
// 建立 p 節點
const p = document.createElement('p')
p.textContent = `I like ${myGame.name}.`

const heading = document.createElement('h1')
heading.textContent = 'Interesting!'

const app = document.querySelector('#root')
app.append(heading, p)

要解決這個問題,只需在專案的根目錄中建立一個.babelrc檔案。可以使用preset-envplugin-proposal-class-properties新增更多預設值。

{
  "presets": ["@babel/preset-env"],
  "plugins": ["@babel/plugin-proposal-class-properties"]
}

現在執行npm run build 一切準備就緒。

Images

假設我們需要引用一張圖片並直接匯入到 JS 檔案中,這樣是無法正常工作的。 為了演示,建立 src/ images 並向其中新增影像,然後嘗試將其匯入到index.js檔案中。

src/index.js

import example from './images/example.png'

/* ... */

執行構建時,再次看到錯誤:

webpack有一些內建的asset modules ,可用於靜態資源。 對於影像型別,我們將使用asset/resource,注意,這裡是一個type,而不是loader

webpack.config.js

module.exports = {
  /* ... */
  module: {
    rules: [
      // Images
      {
        test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
        type: 'asset/resource',
      },
    ],
  },
}

構建後,可以在dist資料夾檢視。

字型和內聯

webpack 還有一個asset module ,可以使用asset/inline內聯某些資料,例如svgs和字型。

src/index.js

import example from './images/example.svg'

/* ... */

webpack.config.js

module.exports = {
  /* ... */
  module: {
    rules: [
      // Fonts and SVGs
      {
        test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
        type: 'asset/inline',
      },
    ],
  },
}

Styles

同樣的需要使用 style loader才能在指令碼中執行類似import 'file.css'的操作。

現在很多人都在使用CSS-in-JSstyled-components和其他工具來將樣式引入到他們的 JS 應用程式中。

當網站只有一個 CSS 檔案,僅能夠載入一個CSS檔案就足夠了。但如果想使用PostCSS,為了能在任何瀏覽器中使用所有最新的CSS特性。或者想使用Sass, CSS前處理器,那就需要使用其它的 loader 處理。

我想使用這三種方法——在Sass中編寫,在PostCSS中處理,以及編譯到CSS。這需要引入一些載入器和依賴項。

  • sass-loader — 載入 SCSS 並編譯為CSS
  • node-sass — Node Sass
  • postcss-loader — 使用 PostCSS 處理 CSS
  • css-loader — 解析 css import
  • style-loader —— 將CSS注入到DOM中
npm i -D sass-loader postcss-loader css-loader style-loader postcss-preset-env node-sass

就像Babel一樣,PostCSS 也需要一個配置檔案 postcss.config.js,在根目錄中建立它,並輸入以下內容:

postcss.config.js

module.exports = {
  plugins: {
    'postcss-preset-env': {
      browsers: 'last 2 versions',
    },
  },
}

為了測試 Sass 和 PostCSS 是否正常工作,建立 src/styles/main.scss,並輸入以下內容:

src/styles/main.scss

$font-size: 1rem;
$font-color: lch(53 105 40);

html {
  font-size: $font-size;
  color: $font-color;
}

現在,將檔案匯入index.js並新增四個 loader 。 它們從最後編譯到第一個,因此列表中最後一個是sass-loader,因為需要編譯,然後是PostCSS,然後是CSS,最後是style-loader,它將CSS注入到DOM 中。

src/index.js

import './styles/main.scss'

/* ... */

webpack.config.js

module.exports = {
  /* ... */
  module: {
    rules: [
      // CSS, PostCSS, and Sass
      {
        test: /\.(scss|css)$/,
        use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
      },
    ],
  },
}

現在,重新構建時,專案中已經應用了SassPostCSS

開發

每次進行更新時都要執行npm run build,站點越大,構建所需的時間就越長,這樣就十分的煩瑣。 為此可以為 webpack 設定兩種配置:

  • 生產配置,用於最小化,優化和刪除所有源對映
  • 開發配置,該配置在伺服器中執行webpack,每次更改都會更新,並具有源對映

開發模式下是在記憶體中執行所有內容,而不是構建一個dist檔案,需要安裝 webpack-dev-server

npm i -D webpack-dev-server

出於演示目的,我們可以僅將開發配置新增到正在構建的當前webpack.config.js檔案中並對其進行測試。 但是,我們開發一般要建立兩個配置檔案:一個生產環境用的 mode: production,一個開發環境用的mode: development

const webpack = require('webpack')

module.exports =  {
  /* ... */
  mode: 'development',
  devServer: {
    historyApiFallback: true,
    contentBase: path.resolve(__dirname, './dist'),
    open: true,
    compress: true,
    hot: true,
    port: 8080,
  },

  plugins: [
    /* ... */
    // Only update what has changed on hot reload
    new webpack.HotModuleReplacementPlugin(),
  ],
})

我們新增mode: development,並建立devServer屬性,其中,預設埠將為8080,自動開啟瀏覽器視窗,並使用hot-module-placement,這需要webpack.HotModuleReplacementPlugin外掛。 這樣模組執行更新而無需完全重新載入頁面-因此,如果你更新某些樣式,則這些樣式將發生變化,並且不用重新載入整個 JS ,大大加快了開發速度。

現在,可以使用webpack serve命令來啟動專案。

package.json

"scripts": {
  "start": "webpack serve"
}
npm start

執行此命令時,將在瀏覽器中自動彈出一個指向localhost:8080的連結。 現在,您可以更新Sass和JavaScript,並觀看其動態更新。

總結

我用 Babel,Sass,PostCSS,生產優化和開發伺服器建立了可用於生產的webpack 5樣板,其中包含本文的所有內容,但會涉及更多細節。 從這裡,可以輕鬆設定React,Vue,Typescript或其他任何您想要的東西。

專案地址:webpack 5 boilerplate

看看它,擺弄它,享受它!


原文:https://www.taniarascia.com/how-to-use-webpack/

程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

交流

文章每週持續更新,可以微信搜尋「 大遷世界 」第一時間閱讀和催更(比部落格早一到兩篇喲),本文 GitHub https://github.com/qq449245884/xiaozhi 已經收錄,整理了很多我的文件,歡迎Star和完善,大家面試可以參照考點複習,另外關注公眾號,後臺回覆福利,即可看到福利,你懂的。

相關文章