使用 webpack 构建 ES6 库

问题描述 投票:0回答:1

我正在寻找类似 html-webpack-plugin 的东西,但它不是 HTML,而是输出到加载其他所有内容的 javascript 文件。我找到了 js-entry-webpack-plugin,但它没有为我输出任何内容,并且似乎没有吐出任何有用的日志记录来告诉我原因。有没有其他东西,内置的或其他的,可以为我做到这一点?

背景

我有一个项目想要构建到一个库中(例如下划线或 jquery),该库可以使用 ES6 在浏览器中动态导入。该库的 API 非常简单,类似于

// index.js:
export const MyAPI = {
    function1: <does stuff>,
    function2: <does other stuff>
}

所以导入它应该是一件轻而易举的事,但我想以 CDN 方式发布它,所以必须动态导入:

// example.js:
const { MyAPI } = await import(<url to MyAPI.js>)

我已在 webpack.config.js 中进行了更改以输出到库:

// webpack.config.js:
    experiments: {
      outputModule: true
    },
    output: {
      filename: 'static/js/[name].[contenthash:8].js',
      path: path.resolve(__dirname, 'build'),
      publicPath: '/',
      chunkFilename: 'static/js/[name].[contenthash:8].chunk.js',
      assetModuleFilename: ({ filename }) => {
        return filename.endsWith('.css') ? 'static/css/[name].[contenthash:8].css' : 'static/media/[name].[hash][ext]'
      },
      library: {
        type: 'module'
      }
    }

该项目产生了数十个 js 块,当我使用 html-webpack-plugin 时,我得到一个带有大量标签的 HTML 文件。我正在寻找一个工具,可以构建一个看起来像这样的 javascript 文件。请注意,MyAPI 是唯一需要在项目外部可见的接口。

// MyAPI.js
import { a, b, c } from 'main.d7791ce7'
import { d, e, f } from '2.62a7f06e'
import { g, h, i } from '19.c38ba2b0.chunk'
... etc
export const MyAPI = {
    function1: a.doSomething,
    function2: d.doSomething,
    ...
}

我考虑过设置 webpack 来生成一个具有我想要的文件名的捆绑文件。我可以将其命名为 MyAPI.js,这样我的问题就可以解决。然而,我会错过分块和缓存清除的好处。我想使用这些功能,同时仍然生成一个漂亮、干净、具有已知名称(无哈希)的单个文件,该文件可以用作访问我的 API 的入口点。

webpack ecmascript-6 module export
1个回答
0
投票

我花了很长时间,但在了解了更多关于 webpack 工作原理的知识后我解决了这个问题。每个 webpack 包必然由需要在同一同步上下文中运行的代码组成。这可能是一种可怕的描述方式,但基本上,webpack 将一个文件视为一个单独的包的唯一方法是是否涉及

await import
。所以解决方案如下所示:

// index.js
const { a } = await import('./abc')
const { d } = await import('./def')

export default {
    function1: a.doSomething,
    function2: d.doSomething
}

由于index.js中没有任何内容需要abc或def中的任何内容现在,因此可以自由地单独捆绑index.js。然后,由于其他所有内容都位于单独的捆绑包中,因此无需指向已编译的捆绑包名称。然后我在 webpack.config.js 中的命名系统中添加一个例外:

output: {
    filename: (pathData) => {
        return pathData.chunk.name?.includes('index') ? 'static/js/MyAPI.js' : 'static/js/[name].[contenthash:8].js'
    }
}

所以现在主包始终称为 MyAPI.js,webpack 将根据需要自动加载其他包。所以我可以这样使用它:

import MyAPI from '/static/js/MyAPI.js'
MyAPI.a()
MyAPI.d()

如果我不输出到 ES6 模块,我不确定这是否有效。具体来说,我认为我无法将使用

await import
导入的内容与其他输出库类型导出。但它与 ES6 配合得很好——webpack 只是确保在此包加载和执行之前加载依赖项。

© www.soinside.com 2019 - 2024. All rights reserved.