javascript - 如何使基于类的自定义元素无副作用,以便 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 的推荐方法是什么?
解决方案
来自 webpack 指南 -将文件标记为无副作用:
上面提到的所有代码都不包含副作用,因此我们可以简单地将属性标记为 false 以通知 webpack 它可以安全地修剪未使用的导出。
因此,设置"sideEffects": false
inpackage.json
告诉 webpack 你的模块是无副作用的。这样它就可以修剪未使用的出口(在您的情况下,未使用的再出口)。这通常由库作者使用。
但这只是等式的一方面。
从 webpack 配置文档 - optimization.sideEffects
:
告诉 webpack 在不使用导出时识别
sideEffects
标记package.json
或规则以跳过标记为不包含副作用的模块。
因此,为了利用前面提到的选项,库使用者必须在他们的 webpack 配置文件中设置optimization.sideEffects
选项:true
// webpack.config.js
module.exports = {
...
optimization: {
sideEffects: true
}
...
}
请注意,在production
mode中,此选项默认启用。因此,您只需将其设置为development
模式。
注意:在这种情况下,您既是模块的作者,又是模块的使用者。
最后,让我们看看你的 webpack 入口点:
// webpack entrypoint
import 'document-register-element';
import 'babel-polyfill';
import { CompDiv } from './index';
如果你稍后在这个文件中不使用你的导入CompDiv
,webpack 将修剪它——假设你已经在你的 webpack 配置中设置"sideEffects": false
了 inpackage.json
和optimization.sideEffects
to 。true
但是,例如,即使您只导入'babel-polyfill'
并且稍后不会在此文件中显式使用它的任何内容,webpack 也不会修剪它,因为package.json
forbabel-polyfill
库不包含"sideEffects": false
.
我希望这能解决问题。
推荐阅读
- swift - deinit 末尾的 Defer 语句会产生警告
- go - 用初始化器理解变量
- python - 如何将类方法的默认参数设置为类变量?
- sql - SQL查询过滤一个表中的日期列是否不存在于连接表的日期范围中?
- ag-grid - 使用带有 angularjs 的外部过滤器 ag-grid 时无法访问单元格值
- python - 为什么最大递归深度与实践中的限制不同?
- php - 为什么 Laravel 和 Pusher 不能在 localhost 上工作,而是在生产上工作?
- swift - 无法识别的“swift_version”键
- javascript - 如何在页面中间放置一个按钮?
- java - 更改 firebase 兄弟值