Webpack

Bootstrap 和 Webpack

如何使用 Webpack 将 Bootstrap 的 CSS 和 JavaScript 包含并打包到您的项目中的官方指南。

bootstrap-webpack.png

想直接跳到最后?您可以从twbs/examples 代码库下载本指南的源代码和示例。您也可以在 StackBlitz 中打开示例进行实时编辑。

设置

我们将从零开始构建一个基于 Webpack 和 Bootstrap 的项目,因此在真正开始之前需要一些先决条件和准备步骤。本指南要求您已安装 Node.js 并熟悉终端操作。

  1. 创建项目文件夹并设置 npm。我们将创建my-project文件夹并使用参数初始化 npm,-y以避免它询问我们所有交互式问题。
mkdir my-project && cd my-project
npm init -y
  1. 安装 Webpack。接下来,我们需要安装 Webpack 的开发依赖项:webpack包括 Webpack 核心组件,webpack-cli以便我们可以从终端运行 Webpack 命令,以及webpack-dev-server运行本地开发服务器。我们使用 --save-dev--development-dependencies 来表明这些依赖项仅用于开发,而非生产环境。
npm i --save-dev webpack webpack-cli webpack-dev-server
  1. 安装 Bootstrap。现在我们可以安装 Bootstrap 了。我们还需要安装 Popper,因为我们的下拉菜单、弹出框和工具提示的定位都依赖于它。如果您不打算使用这些组件,可以省略 Popper 的安装步骤。
npm i --save bootstrap @popperjs/core
  1. 安装其他依赖项。除了 Webpack 和 Bootstrap 之外,我们还需要一些其他依赖项才能使用 Webpack 正确导入和打包 Bootstrap 的 CSS 和 JS 文件。这些依赖项包括 Sass、一些加载器和 Autoprefixer。
npm i --save-dev autoprefixer css-loader postcss-loader sass sass-loader style-loader

现在所有必要的依赖项都已安装完毕,我们可以开始创建项目文件并导入 Bootstrap 了。

项目结构

我们已经创建了my-project文件夹并初始化了 npm。现在,我们将创建 <project_name>src和dist<project_name> 文件夹,以完善项目结构。请在 <project_name> 中运行以下命令my-project,或者手动创建如下所示的文件夹和文件结构。

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

完成后,你的完整项目应该如下所示:

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

目前一切都已就绪,但 Webpack 还无法工作,因为我们还没有填写我们的配置信息webpack.config.js。

配置 Webpack

依赖项安装完毕,项目文件夹也准备就绪,我们可以开始编写代码了。现在我们可以配置 Webpack 并在本地运行我们的项目。

  1. webpack.config.js在编辑器中打开该文件。由于它是空白的,我们需要添加一些样板配置才能启动服务器。这部分配置告诉 Webpack 在哪里查找我们项目的 JavaScript 文件,将编译后的代码输出到哪里(dist),以及开发服务器应该如何运行(从dist文件夹拉取并启用热重载)。
const path = require('path')

module.exports = {
  entry: './src/js/main.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  },
  devServer: {
    static: path.resolve(__dirname, 'dist'),
    port: 8080,
    hot: true
  }
}
  1. 接下来,我们填写 <head> 标签dist/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>
    <script src="./main.js"></script>
  </body>
</html>

我们在这里加入了一些 Bootstrap 样式,div class="container"以便<button>我们可以看到 Webpack 何时加载 Bootstrap 的 CSS。

  1. 现在我们需要一个 npm 脚本来运行 Webpack。打开package.json并添加start下面显示的脚本(你应该已经有了测试脚本)。我们将使用此脚本启动本地 Webpack 开发服务器。
{
  // ...
  "scripts": {
    "start": "webpack serve --mode development",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  // ...
}
  1. 最后,我们可以启动 Webpack 了。my-project在终端中,从该文件夹运行刚刚添加的 npm 脚本:
    npm start

webpack-dev-server.png

在本指南的下一节(也是最后一节)中,我们将设置 Webpack 加载器并导入 Bootstrap 的所有 CSS 和 JavaScript。

导入 Bootstrap

将 Bootstrap 导入 Webpack 需要用到我们在第一部分安装的加载器。我们已经使用 npm 安装了这些加载器,但现在需要配置 Webpack 来使用它们。

  1. 请在配置文件中设置加载器webpack.config.js。您的配置文件现已完成,应与以下代码片段一致。这里唯一的新部分是 module<section> 部分。
    const path = require('path')

module.exports = {
  entry: './src/js/main.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  },
  devServer: {
    static: path.resolve(__dirname, 'dist'),
    port: 8080,
    hot: true
  },
  module: {
    rules: [
      {
        test: /\.(scss)$/,
        use: [
          {
            loader: 'style-loader'
          },
          {
            loader: 'css-loader'
          },
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: () => [
                  require('autoprefixer')
                ]
              }
            }
          },
          {
            loader: 'sass-loader'
          }
        ]
      }
    ]
  }
}

以下是我们需要所有这些加载器的原因回顾。style-loader它将 CSS 注入到HTML 页面的<style><head> 元素中,有助于使用<div> 和<span>,是 Autoprefixer 所必需的,并且允许我们使用 Sass。<head>css-loader@importurl()postcss-loadersass-loader

  1. 现在,让我们导入 Bootstrap 的 CSS。添加以下代码以src/scss/styles.scss导入 Bootstrap 的所有源 Sass 文件。
    // Import all of Bootstrap's CSS
@import "~bootstrap/scss/bootstrap";

您也可以根据需要单独导入我们的样式表。详情请阅读我们的 Sass 导入文档。

  1. 接下来,我们加载 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-bootstrap.png

现在您可以开始添加任何您想要使用的 Bootstrap 组件了。请务必查看完整的 Webpack 示例项目,了解如何添加自定义 Sass 以及如何通过仅导入所需的 Bootstrap CSS 和 JS 部分来优化构建。

生产优化

根据您的具体配置,您可能需要实施一些额外的安全性和速度优化,以利于项目在生产环境中的运行。请注意,Webpack 示例项目中并未应用这些优化,需要您自行实施。

提取 CSS

我们上面配置的功能style-loader可以将 CSS 直接打包到应用包中,这样就无需手动加载 CSS 文件dist/index.html。但是,这种方法可能不适用于严格的内容安全策略 (CSP),而且由于应用包体积较大,可能会成为应用程序的瓶颈。

为了将 CSS 分离出来以便我们可以直接从 <head> 加载它dist/index.html,请使用mini-css-extract-loaderWebpack 插件。

首先,安装插件:

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

然后实例化并在 Webpack 配置中使用该插件:

    --- a/webpack/webpack.config.js
+++ b/webpack/webpack.config.js
@@ -1,8 +1,10 @@
+const miniCssExtractPlugin = require('mini-css-extract-plugin')
 const path = require('path')
 
 module.exports = {
   mode: 'development',
   entry: './src/js/main.js',
+  plugins: [new miniCssExtractPlugin()],
   output: {
     filename: "main.js",
     path: path.resolve(__dirname, "dist"),
@@ -18,8 +20,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,其中包含所有导入的 CSS src/js/main.js。如果您dist/index.html现在在浏览器中查看,会发现样式缺失,因为它现在位于 <style> 文件中dist/main.css。您可以像这样将生成的 CSS 包含到 <style> 文件中dist/index.html:

    
    --- a/webpack/dist/index.html
+++ b/webpack/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 文件

Bootstrap 的 CSS 通过内联 URI 引用了多个 SVG 文件data:。如果您为项目定义了内容安全策略 (CSP),阻止了data:图像的 URI,那么这些 SVG 文件将无法加载。您可以使用 Webpack 的资源模块功能提取内联 SVG 文件来解决此问题。

配置 Webpack 以提取内联 SVG 文件,如下所示:

       --- a/webpack/webpack.config.js
+++ b/webpack/webpack.config.js
@@ -16,6 +16,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/iconsCSS 中并被正确引用。