首页 > 解决方案 > 如何使基于类的自定义元素无副作用,以便 webpack 仅捆绑显式导入的组件

问题描述

我有一组规范 v1 自定义元素,我使用 webpack 4 来捆绑(和 babel-loader 进行转译)。

所有组件看起来都与此类似:

export class CompDiv extends HTMLDivElement {
  constructor(...args) {
    const self = super(...args);
    self.property = null;
    return self;
  }
  connectedCallback() {
    console.log('connected CompDiv');
  }
}

customElements.define('comp-div', CompDiv, { extends: 'div' });

现在,为了能够使用选择性的命名导入从这些组件创建自定义包,我需要将这些文件标记为无副作用

但是,组件注册发生在模块本身中:

customElements.define('comp-div', CompDiv, { extends: 'div' });

据我了解,这一个副作用。

现在我有一个index.js基本上看起来像这样的:

export { CompDiv } from './components/comp-div/comp-div';
...
export { CompBtn } from './components/comp-btn/comp-btn';

我的 webpack 入口点如下所示:

import 'document-register-element';
import 'babel-polyfill';
import { CompDiv } from './index';

现在,当我这样做时,CompBtn(以及 index.js 中的所有其他导出)最终成为捆绑包的一部分,即使它没有导入我的 webpack 入口点。

在 webpack 中允许使用这些 web 组件进行 treeshaking 的推荐方法是什么?

标签: javascriptwebpackes6-modulestree-shaking

解决方案


来自 webpack 指南 -将文件标记为无副作用

上面提到的所有代码都不包含副作用,因此我们可以简单地将属性标记为 false 以通知 webpack 它可以安全地修剪未使用的导出

因此,设置"sideEffects": falseinpackage.json告诉 webpack 你的模块是无副作用的。这样它就可以修剪未使用的出口(在您的情况下,未使用的再出口)。这通常由库作者使用。

但这只是等式的一方面。

从 webpack 配置文档 - optimization.sideEffects

告诉 webpack 在不使用导出时识别sideEffects标记package.json或规则以跳过标记为不包含副作用的模块。

因此,为了利用前面提到的选项,库使用者必须在他们的 webpack 配置文件中设置optimization.sideEffects选项:true

// webpack.config.js
module.exports = {
  ...
  optimization: {
    sideEffects: true
  }
  ...
}

请注意,在productionmode中,此选项默认启用。因此,您只需将其设置为development模式。

注意:在这种情况下,您既是模块的作者,又是模块的使用者

最后,让我们看看你的 webpack 入口点:

// webpack entrypoint
import 'document-register-element';
import 'babel-polyfill';
import { CompDiv } from './index';

如果你稍后在这个文件中不使用你的导入CompDiv,webpack 将修剪它——假设你已经在你的 webpack 配置中设置"sideEffects": false了 inpackage.jsonoptimization.sideEffectsto 。true

但是,例如,即使您导入'babel-polyfill'并且稍后不会在此文件中显式使用它的任何内容,webpack 也不会修剪它,因为package.jsonforbabel-polyfill库不包含"sideEffects": false.

我希望这能解决问题。


推荐阅读