如何使基于类的自定义元素无副作用,因此webpack仅捆绑显式导入的组件 [英] How to make a class-based custom element side-effect-free so webpack only bundles the explicitly imported components
问题描述
我有一组规范v1自定义元素,我正在使用webpack 4进行捆绑(并使用babel-loader进行转换)。
这些组件看上去都很相似
export class CompDiv扩展HTMLDivElement {
构造函数(... args){
const自我= super(... args);
self.property = null;
返回自我;
}
connectedCallback(){
console.log(’connected CompDiv’);
}
}
customElements.define('comp-div',CompDiv,{扩展名:'div'});
现在要能够使用选择性的命名导入从这些组件创建自定义程序包,我需要标记这些无副作用。
组件注册发生在模块本身中:
customElements.define('comp-div',CompDiv,{扩展名:'div'});
据我了解,是的副作用。
现在我有一个 index.js
基本上看起来像这样:
从 ./components/comp-div/comp-div导出{CompDiv};
...
从‘./components/comp-btn/comp-btn’中导出{CompBtn};
我的webpack入口点如下:
import'document-register-element';
导入 babel-polyfill;从'./index'中导入
{CompDiv};
现在,当我这样做时, CompBtn
(以及index.js中的所有其他导出)最终都成为捆绑包的一部分,即使它没有导入到我的webpack入口点中。
推荐的允许方式是
来自Webpack指南-将文件标记为无副作用:
上面提到的所有代码均不包含副作用,因此我们可以简单地将该属性标记为false,以通知 webpack它可以安全地修剪未使用的出口。
因此,将 sideEffects设置为:false
package.json
告诉webpack您的模块没有副作用。这样就可以修剪未使用的出口(在您的情况下为未使用的再出口)。
但这只是等式的一方面。
来自webpack配置文档- optimization.sideEffects
:
告诉webpack识别
包中的
标志.json 或跳过未使用导出标记为不包含副作用的模块的规则。sideEffects
因此,为了利用前面提到的选项,库使用者必须将 optimization.sideEffects
选项设置为 true
在其Webpack配置文件中:
// webpack .config.js
mo dule.exports = {
...
优化:{
sideEffects:true
}
...
}
请注意,在 生产
模式,默认情况下启用此选项。因此,您只需要将其设置为开发
模式。
NB :在这种情况下,您既是模块的 author 也是 consumer 。
最后,让我们来看一下在您的Webpack入口点:
// webpack入口点
import'document-register-元件';
导入 babel-polyfill;从'./index'中导入
{CompDiv};
如果您不使用导入的 CompDiv
在此文件的后面,webpack将对其进行修剪-假设您已在 package.json中设置了
sideEffects:false
code>和 optimization.sideEffects
到Webpack配置中的 true
。
但是,例如,即使您仅仅导入了'babel-polyfill'
,也不会明确使用稍后在此文件中,webpack不会对其进行修剪,因为 babel-polyfill
库的 package.json
不会' t包含 sideEffects:false
。
我希望可以解决问题。
I have a set of spec v1 custom elements which I'm using webpack 4 to bundle (and babel-loader to transpile).
The components all look similar to this:
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' });
Now to be able to create custom packages from these components using selective, named imports I need to mark these files as side-effect-free.
The component registration, though, takes place in the module itself:
customElements.define('comp-div', CompDiv, { extends: 'div' });
As far as I understand, that is a sideeffect.
Now I have an index.js
that basically looks like this:
export { CompDiv } from './components/comp-div/comp-div';
...
export { CompBtn } from './components/comp-btn/comp-btn';
My webpack entry point looks like this:
import 'document-register-element';
import 'babel-polyfill';
import { CompDiv } from './index';
Now when I do this, CompBtn
(and all other exports in index.js) ends up being part of the bundle even though it's not imported in my webpack entry point.
What would be the recommended way of allowing for treeshaking in webpack with these web components?
From webpack guide - Mark the file as side-effect-free:
All the code noted above does not contain side effects, so we can simply mark the property as false to inform webpack that it can safely prune unused exports.
So, setting "sideEffects": false
in package.json
tells webpack that your modules are side effect free. So that it can prune unused exports (in your case, unused re-exports). This is generally used by library authors.
But that's just one side of the equation.
From webpack configuration docs - optimization.sideEffects
:
Tells webpack to recognise the
sideEffects
flag inpackage.json
or rules to skip over modules which are flagged to contain no side effects when exports are not used.
So, in order to leverage that previously mentioned option, the library consumer will have to set the optimization.sideEffects
option to true
in their webpack config file:
// webpack.config.js
module.exports = {
...
optimization: {
sideEffects: true
}
...
}
Note that, in production
mode, this option is enabled by default. So, you'll only need to set it for development
mode.
N.B.: In this case, you are both the author and the consumer of your modules.
Lastly, let's look at your webpack entrypoint:
// webpack entrypoint
import 'document-register-element';
import 'babel-polyfill';
import { CompDiv } from './index';
If you don't use your imported CompDiv
later in this file, webpack will prune it - assuming you've set "sideEffects": false
in package.json
and optimization.sideEffects
to true
in your webpack config.
But, for example, even if you only imported 'babel-polyfill'
and won't explicitly use anything from it later in this file, webpack will not prune it, because the package.json
for babel-polyfill
library doesn't contain "sideEffects": false
.
I hope that clears things up.
这篇关于如何使基于类的自定义元素无副作用,因此webpack仅捆绑显式导入的组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!