【问题标题】:How to build custom bootstrap bundle using Rollup如何使用 Rollup 构建自定义引导包
【发布时间】:2021-07-11 18:11:52
【问题描述】:

根据 Bootstrap 5 官方文档,我们可以从 bootstrap/js/dist 导入预编译的 js 文件,并使用 (Webpack, rollup, ...) 构建自定义包。

https://getbootstrap.com/docs/5.0/getting-started/javascript/#individual-or-compiled

在文档的优化部分,他们给出了如何导入 js 文件的示例。 https://getbootstrap.com/docs/5.0/customize/optimize/#lean-javascript

问题: 我创建了一个名为bootstrap.js的文件

import 'bootstrap/js/dist/tooltip';

我只想使用Tooltip 插件。 我使用以下配置进行汇总

  const plugins = [
    babel({
      exclude: 'node_modules/**',
      // Include the helpers in each file, at most one copy of each
      babelHelpers: 'bundled',
      presets: [
        [
          '@babel/preset-env',
          {
            loose: true,
            bugfixes: true,
            modules: false
          }
        ]
      ]
    }),
    nodeResolve()
  ]

  const bundle = await rollup.rollup({
    input: './js/vendors/bootstrap.js',
    plugins,
  })

  await bundle.write({
    format: 'umd',
    file: './file.js'
  })

生成 file.js 并使用 HTML 页面后,控制台中会出现错误 file.js:1727 Uncaught ReferenceError: process is not defined

我也不能使用引导语法来初始化Tooltip 插件 new bootstrap.Tooltip 给出未定义的错误bootstrap

我可以通过从js/src 文件夹中导入这些文件并按照它们在js/src/index.umd.js 中使用的方式导出它们来实现我想要的,但是按照引导程序官方文档中有关如何导入其插件的方法似乎无法正常工作。

【问题讨论】:

  • 我怀疑您的问题并非特定于引导程序,而是与未为浏览器设置汇总配置有关。例如,nodeResolve 应该配置为browser: truenpmjs.com/package/@rollup/plugin-node-resolve。同样,你应该检查你的 babel 配置。如果您需要更多帮助,请考虑分享一个更完整的示例。

标签: javascript rollup bootstrap-5


【解决方案1】:

不确定如何剖析您的代码 - 您错过了对 Popper 的全部依赖。

但我会这样做(提示:我使用了 BS5 源代码并删除了所有不需要的东西。)

假设您在 Boorstrap 5 的分支上进行编译:

文件: build\rollup.config.mk.js

'use strict'

const path = require('path')
const { babel } = require('@rollup/plugin-babel')
const { nodeResolve } = require('@rollup/plugin-node-resolve')
const replace = require('@rollup/plugin-replace')
const banner = require('./banner.js')

let fileDest = `bootstrap-mk`
const external = ['@popperjs/core']
const plugins = [
  babel({
    // Only transpile our source code
    exclude: 'node_modules/**',
    // Include the helpers in the bundle, at most one copy of each
    babelHelpers: 'bundled'
  })
]
const globals = {
  '@popperjs/core': 'Popper'
}

const rollupConfig = {
  input: path.resolve(__dirname, `../js/index.mk.umd.js`),
  output: {
    banner,
    file: path.resolve(__dirname, `../dist/js/${fileDest}.js`),
    format: 'umd',
    globals
  },
  external,
  plugins
}

rollupConfig.output.name = 'bootstrap'

module.exports = rollupConfig

...还有...

文件: js\index.mk.umd.js

import Tooltip from './src/tooltip'

export default {
  Tooltip
}

然后从命令行调用:rollup --config build/rollup.config.mk.js --sourcemap,或者在packacge.json\“scripts”部分添加类似这样的内容:

  "js-compile-mk": "rollup --config build/rollup.config.mk.js --sourcemap",

...并从命令行调用npm run js-compile-mk

输出将是一个名为:dist\js\bootstrap-mk.js的文件(和一个地图文件)


如果您不想使用 fork,而是使用 node_modules 子文件夹,请更改 build\rollup.config.mk.js 文件中的路径。

【讨论】:

  • 感谢您的回答,但正如我的问题中提到的,我已经通过从src 导入文件来构建自定义引导程序包,但这不是官方文档建议的方式,所以无论如何我认为引导团队缺少一些东西。
  • 将此添加到问题页面:github.com/twbs/bootstrap/issues。我怀疑作者对 SO 的看法。
【解决方案2】:

文档错误

虽然这不是您想要的答案,但正确的答案似乎是“Bootstrap 的文档有错误”。

对于umd 输出,如果我使用以下语法导入:

import Dropdown from '../../node_modules/bootstrap/js/dist/dropdown';

构建失败并出现以下错误:

Error: 'default' is not exported by node_modules\bootstrap\js\dist\dropdown.js, imported by src\js\bootstrap-build.js

与此相反:Files in bootstrap/js/dist use the default export,

什么有效(包括 Popper):

对于读者,假设您来这里是为了解决您遇到的构建问题,以下是适合我的方法。

此答案假定所有依赖项都是使用 NPM 作为开发依赖项安装的,但 Bootstrap 5 除外,它是使用以下命令安装的:

npm install bootstrap

这是 rollup.config.js

import {terser} from 'rollup-plugin-terser';

export default {
    input: './src/js/bootstrap-build.js',
    output: {
        file: 'dist/js/bootstrap.umd.min.js',
        format: "umd",
        name: "bsbundle", // this is the name of the global object
        esModule: false,
        sourcemap: true,
    },
    plugins: [terser({compress: {drop_console: true, module: true}})]
};

这是项目的入口脚本,即bootstrap-build.js,位于/src/js/

import * as Popper from '../../node_modules/@popperjs/core/dist/umd/popper.js';

// from 'js/src/*' source which works
import Modal from '../../node_modules/bootstrap/js/src/modal';
import Tab from '../../node_modules/bootstrap/js/src/tab';
import Dropdown from '../../node_modules/bootstrap/js/src/dropdown';
import Tooltip from '../../node_modules/bootstrap/js/src/tooltip';

export default {
  // Alert,
  // Button,
  // Carousel,
  // Collapse,
  Dropdown,
  Modal,
  // Offcanvas,
  // Popover,
  // ScrollSpy,
  Tab,
  // Toast,
    // Popper,
  Tooltip
}

还有package.json

{
  "name": "bscomponents",
  "version": "1.0.0",
  "description": "Project for building Bootstrap 5 components.",
  "main": "index.js",
  "scripts": {
    "build-bs": "rollup -c"
    },
  "keywords": [],
  "author": "",
  "license": "",
  "dependencies": {
    "bootstrap": "^5.1.3"
  },
  "devDependencies": {
    "@rollup/plugin-multi-entry": "^4.1.0",
    "autoprefixer": "^10.4.0",
    "cross-env": "^7.0.3",
    "postcss": "^8.3.11",
    "rollup": "^2.60.0",
    "rollup-plugin-node-resolve": "^5.2.0",
    "rollup-plugin-terser": "^7.0.2",
  }
}

NPM 构建命令:

NPM run build-bs

构建说明: Bootstrap DropdownTooltip 源文件中导入 Popper 的行被注释掉。

Bundle 包括 PopperDropdownModalTabTooltip

在项目根目录中的文件 index.html 用于测试包。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Bootstrap 5 components</title>
    <!-- custom Bootstrap bundle saves about 21kb -->

    <link rel="stylesheet" href="./node_modules/bootstrap/dist/css/bootstrap-reboot.min.css">
    <link rel="stylesheet" href="./node_modules/bootstrap/dist/css/bootstrap.min.css">

    <!-- and a few simple styles -->
    <style>
        body {
            padding: 5rem;
            margin: 1rem auto;
        }

        .btn-wrapper {
            display: inline-block;
            margin: 1rem auto;
        }

        .btn-wrapper li {
            padding: 1rem
        }

        .tab-pane {
            padding: 2rem;
        }

        ul {
            margin: 3rem
        }
    </style>

</head>

<body>


    <h1>Bootstrap 5 components</h1>

    <ul>
        <li>Dropdown</li>
        <li>Modal (an option in the dropdown)</li>
        <li>Tabs</li>
        <li>Tooltip</li>
    </ul>

    <div class="btn-wrapper dropdown" data-bs-toggle="tooltip" data-bs-placement="top" title="This is a Bootstrap 5 dropdown.">
        <button type="button" id="btnDropDown" class="btn btn-primary btn-calculator dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="true">Options&nbsp;<span class="caret"></span>
        </button>
        <ul class="dropdown-menu" aria-labelledby="btnDropDown">
            <li data-bs-toggle="modal" data-bs-target="#MYMODAL">
                <b>Modal</b>
            </li>
            <li>
                Second option
            </li>
            <li>
                And a final option
            </li>
        </ul>
    </div>

    <div>

        <nav>
            <div class="nav nav-tabs" id="nav-tab" role="tablist">
                <button class="nav-link active" id="nav-tab-1" data-bs-toggle="tab" data-bs-target="#nav-calc-1" type="button" role="tab" aria-controls="nav-calc-1" aria-selected="true">Tab 1</button>
                <button class="nav-link" id="nav-tab-2" data-bs-toggle="tab" data-bs-target="#nav-options-1" type="button" role="tab" aria-controls="nav-options-1" aria-selected="false">Tab 2</button>
            </div>
        </nav>

        <!-- Tab panes -->
        <div class="tab-content" id="nav-tabContent-1">
            <div class="tab-pane fade show active" id="nav-calc-1" role="tabpanel" aria-labelledby="nav-tab-1">
                <p>tab 1</p>
            </div>
            <!--role="tabpanel"-->

            <div class="tab-pane fade show" id="nav-options-1" role="tabpanel" aria-labelledby="nav-tab-2">
                <!-- option tab content -->
                <p>tab 2</p>

            </div>
            <!-- role tabpanel -->

        </div>
        <!--end tab-content-->

    </div>


    <!-- modal -->
    <div class="modal fade" tabindex="-1" id="MYMODAL">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Modal title</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <p>Before you leave, hover over the below buttons.</p>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Click to close">Seconday</button>
                    <button type="button" class="btn btn-primary" data-bs-toggle="tooltip" data-bs-placement="right" title="I do nothing!">Primary</button>
                </div>
            </div>
        </div>
    </div>

    <!-- end modal -->


    <script src="./dist/js/bootstrap.umd.min.js"></script>
    <script>
        var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
        var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
            return new bsbundle.Tooltip(tooltipTriggerEl)
        })
    </script>
</body>

</html>

开发环境:

  • Windows 10
  • 汇总 v2.6
  • 节点 v16.10.0
  • NPM 8.1.3
  • 引导程序 5.1.3

在 VS Code v1.62 的 Bash 终端中运行构建。

结果

包含Popper/dist/js/bootstrap.umd.min.js 的构建包比 Bootstrap 的分布式缩小包节省了大约 21kb。

Probable documentation issue reported on GitHub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    • 2020-06-18
    • 1970-01-01
    • 2014-09-08
    • 1970-01-01
    • 2020-12-27
    相关资源
    最近更新 更多