跳至主要內容 跳至文件導覽

Bootstrap 與 Webpack

如何在專案中使用 Webpack 引入和打包 Bootstrap 的 CSS 和 JavaScript 的官方指南。

想直接跳到最後?twbs/examples 儲存庫下載本指南的原始碼和實際範例。您也可以在 StackBlitz 中開啟此範例進行即時編輯。

什麼是 Webpack?(What is Webpack?)

Webpack 是一個 JavaScript 模組打包工具,處理模組及其相依性以產生靜態資源。它簡化了具有多個檔案和相依性的複雜網頁應用程式的管理。

設定(Setup)

我們從零開始建構一個使用 Bootstrap 的 Webpack 專案,因此在我們真正開始之前有一些先決條件和前置步驟。本指南要求您已安裝 Node.js 並對終端機有一定的熟悉度。

  1. 建立專案資料夾並設定 npm。 我們將建立 my-project 資料夾並使用 -y 參數初始化 npm,以避免它詢問我們所有的互動式問題。

    mkdir my-project && cd my-project
    npm init -y
    
  2. 安裝 Webpack。 接下來我們需要安裝我們的 Webpack 開發相依套件:webpack 是 Webpack 的核心,webpack-cli 讓我們可以從終端機執行 Webpack 命令,webpack-dev-server 讓我們可以執行本地開發伺服器。此外,我們將安裝 html-webpack-plugin 以便能夠將 index.html 儲存在 src 目錄而不是預設的 dist 目錄。我們使用 --save-dev 來表示這些相依套件僅用於開發用途而非正式環境。

    npm i --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin
    
  3. 安裝 Bootstrap。 現在我們可以安裝 Bootstrap。我們還會安裝 Popper,因為我們的下拉選單、彈出提示框和工具提示框依賴它進行定位。如果您不打算使用這些元件,可以在此省略 Popper。

    npm i --save bootstrap @popperjs/core
    
  4. 安裝額外的相依套件。 除了 Webpack 和 Bootstrap 之外,我們還需要一些額外的相依套件來正確地使用 Webpack 引入和打包 Bootstrap 的 CSS 和 JS。這些包括 Sass、一些載入器和 Autoprefixer。

    npm i --save-dev autoprefixer css-loader postcss-loader sass sass-loader style-loader
    

現在我們已經安裝好所有必要的相依套件,我們可以開始建立專案檔案並引入 Bootstrap。

專案結構(Project structure)

我們已經建立了 my-project 資料夾並初始化了 npm。現在我們還要建立 srcdist 資料夾來完善專案結構。從 my-project 執行以下命令,或手動建立如下所示的資料夾和檔案結構。

mkdir {src,src/js,src/scss}
touch src/index.html src/js/main.js src/scss/styles.scss webpack.config.js

完成後,您的完整專案應該看起來像這樣:

my-project/
├── src/
│   ├── js/
│   │   └── main.js
│   ├── scss/
│   │   └── styles.scss
│   └── index.html
├── package-lock.json
├── package.json
└── webpack.config.js

此時,一切都在正確的位置,但 Webpack 還無法運作,因為我們還沒有填寫 webpack.config.js

設定 Webpack(Configure Webpack)

安裝好相依套件並且專案資料夾準備好讓我們開始編碼後,我們現在可以設定 Webpack 並在本地執行專案。

  1. 在編輯器中開啟 webpack.config.js 由於它是空的,我們需要加入一些基本設定才能啟動伺服器。這部分設定告訴 Webpack 在哪裡尋找我們專案的 JavaScript,將編譯後的程式碼輸出到哪裡(dist),以及開發伺服器應該如何運作(從 dist 資料夾拉取並啟用熱重載)。

    'use strict'
    
    const path = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
      mode: 'development',
      entry: './src/js/main.js',
      output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')
      },
      devServer: {
        static: path.resolve(__dirname, 'dist'),
        port: 8080,
        hot: true
      },
      plugins: [
        new HtmlWebpackPlugin({ template: './src/index.html' })
      ]
    }
    
  2. 接下來我們填寫 src/index.html 這是 Webpack 將在瀏覽器中載入的 HTML 頁面,用於使用我們將在後續步驟中加入的打包 CSS 和 JS。在我們這樣做之前,我們必須給它一些東西來渲染,並引入上一步的 output JS。

    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Bootstrap w/ Webpack</title>
      </head>
      <body>
        <div class="container py-4 px-3 mx-auto">
          <h1>Hello, Bootstrap and Webpack!</h1>
          <button class="btn btn-primary">Primary button</button>
        </div>
      </body>
    </html>
    

    我們在這裡加入了一些 Bootstrap 樣式,包括 div class="container"<button>,這樣我們可以看到 Webpack 何時載入了 Bootstrap 的 CSS。

  3. 現在我們需要一個 npm 腳本來執行 Webpack。 開啟 package.json 並加入如下所示的 start 腳本(您應該已經有 test 腳本)。我們將使用此腳本來啟動本地 Webpack 開發伺服器。您還可以加入如下所示的 build 腳本來建置您的專案。

    {
      // ...
      "scripts": {
        "start": "webpack serve",
        "build": "webpack build --mode=production",
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      // ...
    }
    
  4. 最後,我們可以啟動 Webpack。 從終端機中的 my-project 資料夾執行新加入的 npm 腳本:

    npm start
    
    Webpack dev server running

在本指南的下一個也是最後一個部分,我們將設定 Webpack 載入器並引入所有 Bootstrap 的 CSS 和 JavaScript。

引入 Bootstrap(Import Bootstrap)

將 Bootstrap 引入 Webpack 需要我們在第一部分安裝的載入器。我們已經用 npm 安裝了它們,但現在需要設定 Webpack 來使用它們。

  1. webpack.config.js 中設定載入器。 您的設定檔現在已完成,應該與下面的程式碼片段相符。這裡唯一的新部分是 module 區段。

    'use strict'
    
    const path = require('path')
    const autoprefixer = require('autoprefixer')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
      mode: 'development',
      entry: './src/js/main.js',
      output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')
      },
      devServer: {
        static: path.resolve(__dirname, 'dist'),
        port: 8080,
        hot: true
      },
      plugins: [
        new HtmlWebpackPlugin({ template: './src/index.html' })
      ],
      module: {
        rules: [
          {
            test: /\.(scss)$/,
            use: [
              {
                // Adds CSS to the DOM by injecting a `<style>` tag
                loader: 'style-loader'
              },
              {
                // Interprets `@import` and `url()` like `import/require()` and will resolve them
                loader: 'css-loader'
              },
              {
                // Loader for webpack to process CSS with PostCSS
                loader: 'postcss-loader',
                options: {
                  postcssOptions: {
                    plugins: [
                      autoprefixer
                    ]
                  }
                }
              },
              {
                // Loads a SASS/SCSS file and compiles it to CSS
                loader: 'sass-loader',
                options: {
                  sassOptions: {
                    // Optional: Silence Sass deprecation warnings. See note below.
                    silenceDeprecations: [
                      'mixed-decls',
                      'color-functions',
                      'global-builtin',
                      'import'
                    ]
                  }
                }
              }
            ]
          }
        ]
      }
    }
    

    以下是為什麼我們需要所有這些載入器的回顧。style-loader 將 CSS 注入到 HTML 頁面 <head> 中的 <style> 元素,css-loader 幫助處理 @importurl()postcss-loader 是 Autoprefixer 所需的,sass-loader 允許我們使用 Sass。

    注意: 使用最新版本的 Dart Sass 編譯原始 Sass 檔案時會顯示 Sass 棄用警告。這不會阻止編譯或使用 Bootstrap。我們正在研究長期解決方案,在此期間可以忽略這些棄用通知。

  2. 現在,讓我們引入 Bootstrap 的 CSS。 將以下內容加入到 src/scss/styles.scss 以引入所有 Bootstrap 的原始 Sass。

    // Import all of Bootstrap's CSS
    @import "bootstrap/scss/bootstrap";
    

    如果您想要,也可以單獨引入我們的樣式表。閱讀我們的 Sass 引入文件以了解詳情。

  3. 接下來我們載入 CSS 並引入 Bootstrap 的 JavaScript。 將以下內容加入到 src/js/main.js 以載入 CSS 並引入所有 Bootstrap 的 JS。Popper 將透過 Bootstrap 自動引入。

    // Import our custom CSS
    import '../scss/styles.scss'
    
    // Import all of Bootstrap's JS
    import * as bootstrap from 'bootstrap'
    

    您也可以根據需要單獨引入 JavaScript 外掛以減少打包大小:

    import Alert from 'bootstrap/js/dist/alert'
    
    // or, specify which plugins you need:
    import { Tooltip, Toast, Popover } from 'bootstrap'
    

    閱讀我們的 JavaScript 文件以了解更多關於如何使用 Bootstrap 外掛的資訊。

  4. 完成了!🎉 在完全載入 Bootstrap 的原始 Sass 和 JS 後,您的本地開發伺服器現在應該看起來像這樣:

    Webpack dev server running with Bootstrap

    現在您可以開始加入您想使用的任何 Bootstrap 元件。請務必查看完整的 Webpack 範例專案,了解如何引入額外的自訂 Sass 並透過只引入您需要的 Bootstrap CSS 和 JS 部分來最佳化您的建置。

正式環境最佳化(Production optimizations)

根據您的設定,您可能想要實作一些額外的安全性和速度最佳化,這些對於在正式環境中執行專案很有用。請注意,這些最佳化不會套用在 Webpack 範例專案中,由您自行決定是否實作。

提取 CSS(Extracting CSS)

我們上面設定的 style-loader 方便地將 CSS 發出到打包檔案中,因此不需要在 dist/index.html 中手動載入 CSS 檔案。然而,這種方法可能無法在嚴格的內容安全政策下運作,而且由於打包檔案大小較大,可能成為您應用程式的瓶頸。

要分離 CSS 以便我們可以直接從 dist/index.html 載入它,請使用 mini-css-extract-loader Webpack 外掛。

首先,安裝外掛:

npm install --save-dev mini-css-extract-plugin

然後在 Webpack 設定中實例化並使用該外掛:

--- a/webpack.config.js
+++ b/webpack.config.js
@@ -3,6 +3,7 @@
 const path = require('path')
 const autoprefixer = require('autoprefixer')
 const HtmlWebpackPlugin = require('html-webpack-plugin')
+const miniCssExtractPlugin = require('mini-css-extract-plugin')

 module.exports = {
   mode: 'development',
@@ -17,7 +18,8 @@ module.exports = {
     hot: true
   },
   plugins: [
-    new HtmlWebpackPlugin({ template: './src/index.html' })
+    new HtmlWebpackPlugin({ template: './src/index.html' }),
+    new miniCssExtractPlugin()
   ],
   module: {
     rules: [
@@ -25,8 +27,8 @@ module.exports = {
         test: /\.(scss)$/,
         use: [
           {
-            // Adds CSS to the DOM by injecting a `<style>` tag
-            loader: 'style-loader'
+            // Extracts CSS for each JS file that includes CSS
+            loader: miniCssExtractPlugin.loader
           },
           {

再次執行 npm run build 後,會產生一個新的檔案 dist/main.css,其中包含 src/js/main.js 引入的所有 CSS。如果您現在在瀏覽器中檢視 dist/index.html,樣式會遺失,因為它現在在 dist/main.css 中。您可以像這樣在 dist/index.html 中引入產生的 CSS:

--- a/dist/index.html
+++ b/dist/index.html
@@ -3,6 +3,7 @@
   <head>
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link rel="stylesheet" href="./main.css">
     <title>Bootstrap w/ Webpack</title>
   </head>
   <body>

提取 SVG 檔案(Extracting SVG files)

Bootstrap 的 CSS 包含多個透過內嵌 data: URI 引用 SVG 檔案。如果您為專案定義了阻擋圖片 data: URI 的內容安全政策,這些 SVG 檔案將無法載入。您可以使用 Webpack 的資源模組功能提取內嵌 SVG 檔案來解決此問題。

像這樣設定 Webpack 以提取內嵌 SVG 檔案:

--- a/webpack.config.js
+++ b/webpack.config.js
@@ -23,6 +23,14 @@ module.exports = {
   },
   module: {
     rules: [
+      {
+        mimetype: 'image/svg+xml',
+        scheme: 'data',
+        type: 'asset/resource',
+        generator: {
+          filename: 'icons/[hash].svg'
+        }
+      },
       {
         test: /\.(scss)$/,
         use: [

再次執行 npm run build 後,您會發現 SVG 檔案被提取到 dist/icons 並正確地從 CSS 中引用。


發現這裡有錯誤或過時的內容嗎?請在 GitHub 上開啟 issue。需要疑難排解協助嗎?請在 GitHub 上搜尋或發起討論