我正试图找到一种方法来破坏我的模块并使用Babel和Webpack.
如果我从webpack文档(https://webpack.js.org/guides/tree-shaking/)获取示例代码并运行它,那么未使用的模块/函数/其他导出将被标记为未使用的和谐导出,这是预期的结果.在使用-p参数(生产)运行webpack之后,webpack使用UglifyJS删除死的和未使用的代码(到树抖动).
现在,如果我将babel-loader添加到我的webpack配置文件中,我的ES2015模块将被转换,但现在不再标记为未使用的导出.
例如:
export function square(x) {
return x * x;
}
export function cube(x) {
return x * x * x;
}
Run Code Online (Sandbox Code Playgroud)
import {square} from './math.js'
Run Code Online (Sandbox Code Playgroud)
通过webpack运行,没有 babel-loader,该cube函数将被标记为未使用并在编译生产后删除(-p).
通过带有 babel-loader的webpack运行,该cube函数将不会被标记为未使用,并将保留在已编译的包中.
我错过了什么?
这是一个可以重现这种情况的演示回购
https://github.com/Milanzor/babel-and-treeshaking-question
如果我添加.babelrc:
{
"presets": [
["@babel/preset-env", {
"useBuiltIns": "entry",
"debug": true,
"targets": {
"browsers": ["last 2 versions"]
}
}]
]
}
Run Code Online (Sandbox Code Playgroud)
我得到相同的结果,但如果我添加modules: false到preset-env选项,Babel不会将模块编译为ES5,Webpack会将模块再次标记为未使用.
我需要找到一种方法来告诉Webpack我的模块是用Babel编译的,或者我需要找到一种方法告诉Babel自己扫描未使用的代码.
我已经开始学习Angular 2并且遇到了这个术语"树摇晃",从初学者的角度来看,我还没有找到任何好的解释.
什么是树摇晃,我为什么需要它?我该如何使用它?
我有一个与汇总捆绑在一起的React 组件库。然后我在使用 create-react-app 的应用程序设置中使用该库,该应用程序在后台使用 Webpack。我希望 Webpack 对组件库进行 tree-shake。在构建应用程序包并对其进行分析后,我发现该库要么根本没有摇树,要么摇树在库上不起作用,因为它首先不可摇树。为什么摇树不起作用?我究竟做错了什么?
? rollup.config.js(React 组件库的打包配置)
import babel from 'rollup-plugin-babel'
import commonjs from 'rollup-plugin-commonjs'
import autoExternal from 'rollup-plugin-auto-external'
import resolve from 'rollup-plugin-node-resolve'
import reactSvg from 'rollup-plugin-react-svg'
import url from 'rollup-plugin-url'
import string from 'rollup-plugin-string'
import pureanno from 'rollup-plugin-pure-annotation'
import pkg from './package.json'
const { getSVGOConfig } = require('./scripts/getSVGOConfig')
const MAX_INLINE_FILE_SIZE_KB = 100
export default {
input: 'src/index.js',
output: [
{
file: pkg.module,
format: 'es',
},
],
plugins: [
autoExternal(),
babel({ …Run Code Online (Sandbox Code Playgroud) 我们目前正在尝试优化复杂的 Angular 应用程序(性能和包大小)。
我们发现我们有部分未使用的组件,但我们不能 100% 确定它们。无论如何......我们目前要问的问题是在 Angular 中摇树究竟是如何工作的。
问题 1)如果在模块的声明、导入或提供者数组中有条目,但该模块没有在任何地方使用,它们是否也通过摇树移除或包含在最终包中?
例子:
@NgModule({
imports: [
FirstModule,
SecondModule // Is not used anymore (probably) but imported here
],
declarations: [SampleComponent] // Is not used anymore (probably) but imported here
})
export class SampleModule {
}
Run Code Online (Sandbox Code Playgroud)
信息:该模块/组件的路由已被删除。
问题 2)仅从路由模块中移除这些组件是否足以使摇树过程成功?
问题 3)要使摇树过程达到最佳状态,应该具备哪些条件?
使用 Angular 8.2 版
我有一个 Gatsby 站点,它使用了许多软件包。其中一个包是从我们的 monorepo 发布的:@example/forms. 该包包含许多命名导出,一个用于我们在站点上使用的每个表单组件。有相当多的形式,有些是相当复杂的多步形式,大小不一。
目前,Gatsby/Webpack 在 treeshaking 方面做得很好,并且确实产生了大量的包,一些常见的包和站点的每个页面一个,包含仅在该页面上使用的任何本地资产或组件。然而,尽管大多数组件只在一个页面上使用,但所有组件@example/forms都被添加到commons包中。这导致commons在每个页面上加载的包不必要的膨胀。
如果感觉应该可以将其中的各个组件@example/forms拆分为特定于页面的包,但我不确定我是否希望太多。例如,如果表单 A 仅用于第 4 页,我希望仅将表单 A 添加到第 4 页的捆绑包中。
这是支持的东西吗,如果支持,是什么阻止了这种情况的发生。
@example/forms被transpiled与ES6出口保持不变,并sideEffects设置为false在其package.json。
它的main文件是index.js(重新)将所有表单组件从它们自己的文件中导出为单独命名的导出:
export {default as FormA} from './forms/formA'
export {default as FormB} from './forms/formB'
...
Run Code Online (Sandbox Code Playgroud)
这可能是相关的另一件事是,全部来自出口@example/forms 的盖茨比网站内使用,只是在不同的页面。看起来也许 tree-shaking 不能跨 bundle 使用,即首先执行 tree-shaking,然后将剩下的拆分成 bundle。使用该逻辑,@example/forms将在多个页面上使用并移至公共区域。然而,这绝对不是最佳的,希望不是正在发生的事情。
我和我的同事发生争执,我们似乎无法从任何官方来源(MDN,webpack文档......)找到答案.我的研究也没有取得多少成果.即使在进口方面也似乎存在疑问.
我们的设置是Webpack,Babel和典型的React/Redux应用程序.举个例子:
export * from './actions';
export * from './selectors';
export * from './reducer';
export { default } from './reducer';
Run Code Online (Sandbox Code Playgroud)
这允许我将Redux模块分成逻辑部分,使代码更易于阅读和维护.
然而,我的一些同事认为export * from,事实上可能会损害webpack树木震动的能力,因为他们相信在出口实际上只是再出口时会使用出口.
所以我的问题是,有没有事实证明或反驳这一点?
我正在使用所有与 Angular 相关的软件包的最新版本(所以是 Angular 10)。
我想向组件添加一些代码,但我只希望这些代码存在于开发中,而不是生产版本中。它需要在产品构建中完全剥离。我发现了这个评论,这表明环境会自动执行此操作(因为它们是const)。
我尝试在我的应用程序中使用该确切代码,但开发代码仍在生产版本中。我将代码复制到我用 制作的新测试应用程序中ng new,它确实在那里正常工作。
我应该寻找什么东西,我该如何解决这个问题?这是否可能是因为我有 CommonJS 依赖项,如果是这样,我可以做些什么(因为我无法删除这些依赖项)?
一些注意事项:
environment对象从未写入代码库中的任何地方,我已经进行了彻底的搜索。(无论如何它只在少数地方使用。)if (false) { }为界的代码被正确剥离。environment{.prod}.ts并不能解决问题。这是environment.prod.ts(environment.ts是相同的,只是用false而不是true):
export const environment = {
production: true
};
export * from './services/services';
Run Code Online (Sandbox Code Playgroud)
这main.ts是我正在测试的:
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { environment } from …Run Code Online (Sandbox Code Playgroud) 我创建了这个例子
模块.js
import moment from "moment";
export function square(x) {
return x * x;
}
export function cube(x) {
return moment.format(x * x * x);
}Run Code Online (Sandbox Code Playgroud)
main.js
import {square} from "./module";
console.log(square(1));Run Code Online (Sandbox Code Playgroud)
我注意到它还在我的包中包含了 moment 库,尽管我没有在 square 函数中使用它。如果我从 module.js 中删除 moment 导入,树摇动效果很好,我只在我的包中看到 square 。
这就是摇树的工作原理吗?如果我想在 module.js 文件中使用外部库,除了将代码拆分到不同的文件中之外,还有其他解决方法吗?
在执行以下捆绑可视化时,Webpack将包括捆绑中的所有 d3.js.问题可以通过这样做来解决,但这有点挫败了自动树摇动的目的.import { select } from 'd3'import { select } from 'd3-selection'
在我们的非库代码中,树摇动似乎在简单的情况下起作用.
我们"modules": false在我们.babelrc中使用以保留模块语法并'module'在webpack.config.js resolve: { mainFields: ['module', 'browser', 'main'] }中使用resolve 来选择d3的基于模块的代码.如您所见,导入的node_modules/d3/index.js在ES6模块中进行了分区,而不是单片浏览器包或CommonJS导出.
这应该在webpack github页面上作为一个问题发布,还是我做错了什么?这是使用图书馆的所有最新版本(d3@4.5.0,webpack@2.2.1,等)
编辑:似乎这与以下问题有关:
我已经尝试将UglifyJSPlugin添加到webpack 4项目中,根据webpack文档,我仍然看到我的包中的死代码甚至注释导致我认为我的uglify插件配置没有被使用.
该文件指出,"为了充分利用树摇,你必须...
-使用ES2015模块语法(即进口和出口).做
-添加一个'副作用’进入到项目的文件的package.json.完成.
-包括支持死代码删除的缩小器(例如UglifyJSPlugin)." DONE
仍然,未使用/未导入的左键盘功能和注释包含在我的包中.
所有的配置都可以在这里看到.根据我看到的结果,我怀疑这与我的webpack配置中的uglify 设置有关.
要重现,请拉回购并运行yarn build
tree-shaking ×10
webpack ×8
javascript ×5
angular ×3
ecmascript-6 ×2
angular-cli ×1
angular8 ×1
babeljs ×1
bundle ×1
d3.js ×1
es6-modules ×1
gatsby ×1
reactjs ×1
rollup ×1
typescript ×1
uglifyjs ×1
webpack-3 ×1