我正在使用Angular CLI构建一个使用该--prod
开关进行生产的应用程序.该包在dist目录中创建.有没有办法知道哪些类和函数在树形图形和所有其他步骤后实际放入了包中?
现在,我正在使用 Vite2.x 使用“rollup-plugin-visualizer”构建我的项目,我发现它构建了整个 lodash 包
这是一个示例存储库,显示了此线程中报告的问题的示例:https : //github.com/Eux86/tree-shaking-barrel-test/blob/master/README.md
我试图了解使用 Barrel 文件从库项目中导出函数和类的效果是什么,当将它导入到另一个使用 webpack 的项目中并且应该能够对包进行 treeshake 时。
假设我有一个项目:
图书馆
索引.ts
libA.ts
库文件
index.ts 有这个代码:
export { LibAMain } from 'LibA';
export { LibBMain } from 'LibB';
Run Code Online (Sandbox Code Playgroud)
所以我使用 index 作为桶文件来导出我将在我的库中开发的所有函数。
第二个项目将是:
图书馆用户
Index.ts 有这样的代码:
import { LibAMain } from 'library'
LibAMain();
Run Code Online (Sandbox Code Playgroud)
现在:library-user 是使用 webpack 构建的,我希望它能够对 MyLib 中未使用的库进行 treeshake,但是当我查看生成的包时,我看到它包含引导 LibA.js 和 LibB.js,这不应该在那里:
如果我将 index.ts 更改为:
import { LibAMain } from 'library/lib/LibA'
LibAMain();
Run Code Online (Sandbox Code Playgroud)
然后 webpack 很好地完成了它的工作,我只在最终包中看到了 LibA:
TL;DR:我怎样才能继续使用桶索引文件并只从“库”中导入所有内容,但仍然使 treeshaking 工作?
感谢您的任何帮助 :)
我有一个包含多个react组件的库,并且我想使该库可树状摇动,以便在导入类似
import { Checkbox } from 'my-react-components'
Run Code Online (Sandbox Code Playgroud)
我不导入整个捆绑包。
我的index.js看起来像这样
export { default as Button } from './components/Button'
export { default as Checkbox } from './components/Checkbox'
export { default as FlexView } from './components/FlexView'
export { default as Radio } from './components/Radio'
export { default as Select } from './components/Select'
export { default as TextInput } from './components/TextInput'
export { default as Toggle } from './components/Toggle'
Run Code Online (Sandbox Code Playgroud)
我捆绑使用webpack
module.exports = {
mode: 'production',
entry: './src/index.ts',
output: {
path: path.resolve('./lib'),
filename: 'react-components.js',
libraryTarget: …
Run Code Online (Sandbox Code Playgroud) 是否有一些东西可以让 next.js 执行树摇动/从依赖项中删除死代码?我已经导出了两个这样的对象:
library.js
export const foo = {foo:"foo"}
export const bar = {bar:"bar"}
Run Code Online (Sandbox Code Playgroud)
在我的 next.js 应用程序中,我喜欢这样:
page.tsx
import { foo } from 'library';
console.log(foo);
Run Code Online (Sandbox Code Playgroud)
所以现在我预计生产构建将不包含bar
,并且确实有些事情似乎是正确的,因为生成了这一行:
.next/server/chunks/621.js
/* unused harmony exports bar */
Run Code Online (Sandbox Code Playgroud)
但令人困惑的是,当我在浏览器中加载应用程序时,网络流量表明包含未使用的导出:
http://localhost:3001/_next/static/chunks/pages/page-0b2b13a7513f2849d855.js
(self.webpackChunk_N_E = self.webpackChunk_N_E || []).push([[3031], {
80621: function(e, r, n) {
"use strict";
...
const l = a.object({
foo: "foo"
});
a.object({
bar: "bar"
});
},
Run Code Online (Sandbox Code Playgroud)
为什么构建会识别未使用的导出,但不会将它们从传输到浏览器的有效负载中删除?Next 是否有一个设置希望我们启用?某种后处理实际上会修剪未使用的导出?
我认为在Angular-cli树抖动中排除组件的问题非常相似,但我似乎无法从中得到任何东西.
基本上我有一个动态组件工厂,如我如何使用/创建动态模板来编译动态组件与Angular 2.0?.
当我使用最新的Angular CLI和非生产设置构建它时,一切正常.但是,一旦我使用生产设置,我在尝试加载具有动态创建内容的页面时立即在浏览器中获得以下错误跟踪:
例外:找不到'e'的NgModule元数据.
ORIGINAL STACKTRACE:
main.dc05ae9 ... .bundle.js:格式:4731
错误:找不到'e'的NgModule元数据.
at t(vendor.c18e6df ... .bundle.js:格式化:76051)
at t.resolve(vendor.c18e6df ... .bundle.js:格式化:20624)
at t.getNgModuleMetadata(vendor.c18e6df ... .bundle.js:formatted: 20169)
在t._compileModuleAndAllComponents(vendor.c18e6df ... .bundle.js:格式化:40462)的t._loadModules(vendor.c18e6df ... .bundle.js:格式化:40474
)
at t.compileModuleAndAllComponentsSync(vendor.c18e6df ... .bundle. js:格式化:40436)
在e.createComponentFactory(main.dc05ae9 ... .bundle.js:格式:4789)
这是我的组件工厂类:
@Injectable()
export class DynamicTypeBuilder {
constructor() {
}
private _cacheOfFactories: {[templateKey: string]: ComponentFactory<any>} = {};
private compiler: Compiler = new JitCompilerFactory([{useDebug: false, useJit: true}]).createCompiler();
public createComponentFactory<COMPONENT_TYPE>(type: any, template: string, additionalModules: any[] = []): Observable<ComponentFactory<COMPONENT_TYPE>> {
let …
Run Code Online (Sandbox Code Playgroud) 我刚刚用CLI创建了一个新的Angular 4项目: ng new test
版本:
@angular/cli: 1.0.0
node: 6.10.0
os: win32 x64
@angular/common: 4.0.1
@angular/compiler: 4.0.1
@angular/core: 4.0.1
@angular/forms: 4.0.1
@angular/http: 4.0.1
@angular/platform-browser: 4.0.1
@angular/platform-browser-dynamic: 4.0.1
@angular/router: 4.0.1
@angular/cli: 1.0.0
@angular/compiler-cli: 4.0.1
Run Code Online (Sandbox Code Playgroud)
但是,由于我未使用的类FooBar
仍在main.*.js
文件中,因此树抖动无法正常工作.
我的示例组件TS文件(FooBar不应该在输出中):
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app works!';
}
export class FooBar {
foo = "hello";
}
Run Code Online (Sandbox Code Playgroud)
我试图使用汇总(如文档中所述),但这不起作用......
有没有一种简单的方法来启用树木摇晃?(我希望在通过CLI创建项目时默认启用它).
更新:我正在使用ng build --prod
它仍然没有被震动..
我一直在努力学习如何编写树摇动友好的代码,但遇到了一个不可避免的副作用的问题,我不知道如何处理.
在我的一个模块中,我访问全局Audio
构造函数并使用它来确定浏览器可以播放哪些音频文件(类似于Modernizr的工作方式).每当我尝试树摇动我的代码时,Audio
即使我不在我的文件中导入模块,元素及其所有引用也不会被消除.
let audio = new Audio(); // or document.createElement('audio')
let canPlay = {
ogg: audio.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, '');
mp3: audio.canPlayType('audio/mpeg; codecs="mp3"').replace(/^no$/, '');
// ...
};
Run Code Online (Sandbox Code Playgroud)
我知道包含副作用的代码无法消除,但我找不到的是如何处理不可避免的副作用.我不能只是访问全局对象来创建audio
检测功能支持所需的元素.那么我如何处理访问全局浏览器函数/对象(我在这个库中做了很多)的方式,树摇动友好,仍然允许我消除代码?
我正在尝试使 Nuxt.js / Vuetify 模块提供的自动摇树功能正常工作。在我的 nuxt.config.js 我有:
buildModules: [
['@nuxtjs/vuetify', {treeShake: true}]
],
Run Code Online (Sandbox Code Playgroud)
然而,我目前只使用一两个组件,但我仍然得到一个非常大的 vendor.app(添加 treeshake 选项对大小没有影响)
Hash: 9ab07d7e13cc875194be
Version: webpack 4.41.2
Time: 18845ms
Built at: 12/10/2019 11:04:48 AM
Asset Size Chunks Chunk Names
../server/client.manifest.json 12.2 KiB [emitted]
5384010d9cdd9c2188ab.js 155 KiB 1 [emitted] [immutable] commons.app
706a50a7b04fc7741c9f.js 2.35 KiB 4 [emitted] [immutable] runtime
8d5a3837a62a2930b94f.js 34.7 KiB 0 [emitted] [immutable] app
9d5a4d22f4d1df95d7a7.js 1.95 KiB 3 [emitted] [immutable] pages/login
LICENSES 389 bytes [emitted]
a0699603e56c5e67b811.js 170 KiB 6 [emitted] [immutable] vendors.pages/login
b1019b7a0578a5af9559.js 265 KiB …
Run Code Online (Sandbox Code Playgroud) 我有一组使用vpack 4捆绑在一起的spec v1自定义元素(和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' });
Run Code Online (Sandbox Code Playgroud)
现在,要能够使用选择性的命名导入从这些组件创建自定义程序包,我需要将这些文件标记为没有副作用。
但是,组件注册发生在模块本身中:
customElements.define('comp-div', CompDiv, { extends: 'div' });
Run Code Online (Sandbox Code Playgroud)
据我了解,这是一个副作用。
现在我有一个index.js
基本上看起来像这样的:
export { CompDiv } from './components/comp-div/comp-div';
...
export { CompBtn } from './components/comp-btn/comp-btn';
Run Code Online (Sandbox Code Playgroud)
我的webpack入口点如下所示:
import 'document-register-element';
import 'babel-polyfill';
import { CompDiv } from './index';
Run Code Online (Sandbox Code Playgroud)
现在,当我执行此操作时CompBtn
(以及未将其导入到我的webpack入口点中),(以及index.js中的所有其他导出结果)最终成为捆绑包的一部分。
建议使用这些Web组件在webpack中进行树状握手的推荐方法是什么?
tree-shaking ×10
webpack ×5
angular ×3
angular-cli ×2
es6-modules ×2
javascript ×2
angular4 ×1
import ×1
lodash ×1
next.js ×1
nuxt.js ×1
reactjs ×1
rollupjs ×1
side-effects ×1
vite ×1
vuetify.js ×1