You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
原因是 webpack Tree Shaking 的实现原理 中提到的, 由于ddddddddd is declared but its value is never read.被 ts-loader 给删除了,我们篡改下 ts-loader 的代码,使得它保留 import { ddddddddd } from "./ddd" 这行代码
// react-app-polyfill/ie11'use strict';if(typeofPromise==='undefined'){// Rejection tracking prevents a common issue where React gets into an// inconsistent state due to an error, but it gets swallowed by a Promise,// and the user has no idea what causes React's erratic future behavior.require('promise/lib/rejection-tracking').enable();self.Promise=require('promise/lib/es6-extensions.js');}// Make sure we're in a Browser-like environment before importing polyfills// This prevents `fetch()` from being imported in a Node test environmentif(typeofwindow!=='undefined'){// fetch() polyfill for making API calls.require('whatwg-fetch');}// Object.assign() is commonly used with React.// It will use the native implementation if it's present and isn't buggy.Object.assign=require('object-assign');// Support for...of (a commonly used syntax feature that requires Symbols)require('core-js/features/symbol');// Support iterable spread (...Set, ...Map)require('core-js/features/array/from');
// webpack/lib/Compilation.jsclassCompilation{getDependencyReference(module,dependency){// TODO remove dep.getReference existence check in webpack 5if(typeofdependency.getReference!=='function')returnnullconstref=dependency.getReference()if(!ref)returnnullreturnthis.hooks.dependencyReference.call(ref,dependency,module)}}// webpack/lib/dependencies/HarmonyImportSideEffectDependency.jsclassHarmonyImportSideEffectDependencyextendsHarmonyImportDependency{getReference(){if(this._module&&this._module.factoryMeta.sideEffectFree)returnnull;returnsuper.getReference();}}
例子 🌰
下面以一个业务项目为例, 我们添加了若干文件来验证测试
src/views/act-choose-goods/index.ts
aaa.ts
与ddd.ts
都会被删除aaa.ts
还存在,只有ddd.ts
被删除了,那么 webpack 为什么没有删除aaa.ts
?原因是 webpack Tree Shaking 的实现原理 中提到的, 由于
ddddddddd is declared but its value is never read.
被 ts-loader 给删除了,我们篡改下 ts-loader 的代码,使得它保留import { ddddddddd } from "./ddd"
这行代码现在我们发现打包后
ddd.ts
也被保留了下来...原因分析
为什么 webpack 没有删除未使用到的
aaa.ts
与ddd.ts
模块?原因是 webpack 无法确认
aaa.ts
与ddd.ts
是否有副作用。比如我们常在代码中这样去 import 一个 polyfill 来兼容低版本浏览器, 在这种情况下我们虽然没有使用 react-app-polyfill 的导出, 但是不能删除import 'react-app-polyfill/ie11'
这行代码因为
react-app-polyfill/ie11
直接修改了 window、Object 等全局对象, 这段代码有副作用, 即使没有用到其导出也应该被保留下来又比如当你没用 CSS Modules 时, 通常只需
import 'antd/dist/reset.css';
, 此时也不会用到 *.css 模块的导出, 说明 *.css 模块也有副作用不能轻易被删除对于这种情况, 我们可以在项目的
package.json
中可以通过 sideEffects 字段声明哪些文件是有副作用, 如下表示仅 *.css 模块有副作用当确认了 *.ts 没有副作用后, 再看一下结果发现
aaa.ts
与ddd.ts
最终被成功删除了实现原理
当我们没有在
package.json
中声明 sideEffects 字段时, 可以看到对于 aaa.ts 模块的 hasSideEffects 为 true, 即是有副作用的, 那么对于 *.ts 模块的factoryMeta.sideEffectFree
的值都将为默认的 undefined当我们声明 sideEffects 字段后, 那么某个模块的文件后缀会与 sideEffects 进行类似正则匹配, 对于 *.ts 模块没有被 *.css 表达式匹配上则 hasSideEffects 为 false,
factoryMeta.sideEffectFree
被赋值为 true即 sideEffects 字段决定
factoryMeta.sideEffectFree
的值, 而factoryMeta.sideEffectFree
的值将决定该模块是否被 Tree Shaking下面讲一下 HarmonyImportSideEffectDependency, 如上图 iteratorDependency 函数中当 ref 存在 && ref.module 也存在等条件成立时也会被添加到 blockInfoModules 中(可以认为没有添加到 blockInfoModules 中的模块是不会生成到打包后的代码中)。
那么最关键的因素就是
this._module.factoryMeta.sideEffectFree
的值, 如果值为 true, 那么 getDependencyReference 函数返回值为 null, ref 为 null 就结束了factoryMeta.sideEffectFree
的值其实我们上面已经讨论过了factoryMeta.sideEffectFree
的值为 undefined, 继续调用 super.getReference() 将会返回一个有值的 reffactoryMeta.sideEffectFree
的值为 true, ref 即为 null, 自此被引用了但未实际用到其导出的aaa.ts
、ddd.ts
、bbb.ts
等模块都不会添加到 blockInfoModules 中,即不会出现在打包后的文件中小结
The text was updated successfully, but these errors were encountered: