diff --git a/package.json b/package.json index c67ca3cad7c..94ddc86f692 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,8 @@ "test:vue:watch": "npm run test:vue --- --watch", "test:reactive-vue": "jest packages/reactive-vue", "test:reactive-vue:watch": "npm run test:reactive-vue --- --watch", + "test:antd": "jest packages/antd", + "test:next": "jest packages/next", "test:watch": "jest --watch", "test:prod": "jest --coverage --silent", "preversion": "npm run build && npm run lint && npm run test", diff --git a/packages/antd/__tests__/sideEffects.spec.ts b/packages/antd/__tests__/sideEffects.spec.ts new file mode 100644 index 00000000000..98d20a9c029 --- /dev/null +++ b/packages/antd/__tests__/sideEffects.spec.ts @@ -0,0 +1,89 @@ +import SideEffectsFlagPlugin from 'webpack/lib/optimize/SideEffectsFlagPlugin' +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { sideEffects, name: baseName } = require('../package.json') + +test('sideEffects should be controlled manually', () => { + // if config in pkg.json changed, please ensure it is covered by jest. + expect(sideEffects).toStrictEqual([ + 'dist/*', + 'esm/*.js', + 'lib/*.js', + 'src/*.ts', + '*.less', + '**/*/style.js', + ]) +}) + +test('dist/*', () => { + // eg. import "@formily/antd/dist/antd.css" + expect( + SideEffectsFlagPlugin.moduleHasSideEffects('dist/antd.css', 'dist/*') + ).toBeTruthy() + expect( + SideEffectsFlagPlugin.moduleHasSideEffects( + 'dist/formily.antd.umd.development.js', + 'dist/*' + ) + ).toBeTruthy() + expect( + SideEffectsFlagPlugin.moduleHasSideEffects( + 'dist/formily.antd.umd.production.js', + 'dist/*' + ) + ).toBeTruthy() +}) + +test('esm/*.js & lib/*.js', () => { + // expected to be truthy + // eg. import FormilyAntd from "@formily/antd/esm/index" + expect( + SideEffectsFlagPlugin.moduleHasSideEffects('esm/index.js', 'esm/*.js') + ).toBeTruthy() + expect( + SideEffectsFlagPlugin.moduleHasSideEffects('lib/index.js', 'lib/*.js') + ).toBeTruthy() + + // expected to be falsy + // eg. import Input from "@formily/antd/esm/input/index" => will be compiled to __webpack_require__("./node_modules/@formily/antd/esm/input/index.js") + // It should be removed by webpack if not used after imported. + expect( + SideEffectsFlagPlugin.moduleHasSideEffects('esm/input/index.js', 'esm/*.js') + ).toBeFalsy() + expect( + SideEffectsFlagPlugin.moduleHasSideEffects( + 'esm/array-base/index.js', + 'esm/*.js' + ) + ).toBeFalsy() + expect( + SideEffectsFlagPlugin.moduleHasSideEffects('lib/input/index.js', 'lib/*.js') + ).toBeFalsy() +}) + +test('*.less', () => { + // eg. import "@formily/antd/lib/input/style.less" + expect( + SideEffectsFlagPlugin.moduleHasSideEffects( + `${baseName}/lib/input/style.less`, + '*.less' + ) + ).toBeTruthy() +}) + +test('**/*/style.js', () => { + // eg. import "@formily/antd/lib/input/style" will be compiled to __webpack_require__("./node_modules/@formily/antd/lib/input/style.js") + // so we can match the `*style.js` only, not `**/*/style*` may be cause someting mismatch like `@formily/antd/lib/xxx-style/index.js` + const modulePathArr = [ + 'lib/input/style.js', + `${baseName}/lib/input/style.js`, + `./node_modules/${baseName}/style.js`, + ] + + modulePathArr.forEach((modulePath) => { + const hasSideEffects = SideEffectsFlagPlugin.moduleHasSideEffects( + modulePath, + '**/*/style.js' + ) + expect(hasSideEffects).toBeTruthy() + }) +}) diff --git a/packages/antd/package.json b/packages/antd/package.json index 8c6f6ed08a5..d464f8a5778 100644 --- a/packages/antd/package.json +++ b/packages/antd/package.json @@ -13,7 +13,8 @@ "esm/*.js", "lib/*.js", "src/*.ts", - "*.less" + "*.less", + "**/*/style.js" ], "repository": { "type": "git", diff --git a/packages/next/__tests__/sideEffects.spec.ts b/packages/next/__tests__/sideEffects.spec.ts new file mode 100644 index 00000000000..e199b93ef34 --- /dev/null +++ b/packages/next/__tests__/sideEffects.spec.ts @@ -0,0 +1,89 @@ +import SideEffectsFlagPlugin from 'webpack/lib/optimize/SideEffectsFlagPlugin' +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { sideEffects, name: baseName } = require('../package.json') + +test('sideEffects should be controlled manually', () => { + // if config in pkg.json changed, please ensure it is covered by jest. + expect(sideEffects).toStrictEqual([ + 'dist/*', + 'esm/*.js', + 'lib/*.js', + 'src/*.ts', + '*.scss', + '**/*/style.js', + ]) +}) + +test('dist/*', () => { + // eg. import "@formily/next/dist/next.css" + expect( + SideEffectsFlagPlugin.moduleHasSideEffects('dist/next.css', 'dist/*') + ).toBeTruthy() + expect( + SideEffectsFlagPlugin.moduleHasSideEffects( + 'dist/formily.next.umd.production.js', + 'dist/*' + ) + ).toBeTruthy() + expect( + SideEffectsFlagPlugin.moduleHasSideEffects( + 'dist/formily.next.umd.production.js', + 'dist/*' + ) + ).toBeTruthy() +}) + +test('esm/*.js & lib/*.js', () => { + // expected to be truthy + // eg. import Formilynext from "@formily/next/esm/index" + expect( + SideEffectsFlagPlugin.moduleHasSideEffects('esm/index.js', 'esm/*.js') + ).toBeTruthy() + expect( + SideEffectsFlagPlugin.moduleHasSideEffects('lib/index.js', 'lib/*.js') + ).toBeTruthy() + + // expected to be falsy + // eg. import Input from "@formily/next/esm/input/index" => will be compiled to __webpack_require__("./node_modules/@formily/next/esm/input/index.js") + // It should be removed by webpack if not used after imported. + expect( + SideEffectsFlagPlugin.moduleHasSideEffects('esm/input/index.js', 'esm/*.js') + ).toBeFalsy() + expect( + SideEffectsFlagPlugin.moduleHasSideEffects( + 'esm/array-base/index.js', + 'esm/*.js' + ) + ).toBeFalsy() + expect( + SideEffectsFlagPlugin.moduleHasSideEffects('lib/input/index.js', 'lib/*.js') + ).toBeFalsy() +}) + +test('*.scss', () => { + // eg. import "@formily/next/lib/input/style.scss" + expect( + SideEffectsFlagPlugin.moduleHasSideEffects( + `${baseName}/lib/input/style.scss`, + '*.scss' + ) + ).toBeTruthy() +}) + +test('**/*/style.js', () => { + // eg. import "@formily/next/lib/input/style" will be compiled to __webpack_require__("./node_modules/@formily/next/lib/input/style.js") + // so we can match the `*style.js` only, not `**/*/style*` may be cause someting mismatch like `@formily/next/lib/xxx-style/index.js` + const modulePathArr = [ + 'lib/input/style.js', + `${baseName}/lib/input/style.js`, + `./node_modules/${baseName}/style.js`, + ] + + modulePathArr.forEach((modulePath) => { + const hasSideEffects = SideEffectsFlagPlugin.moduleHasSideEffects( + modulePath, + '**/*/style.js' + ) + expect(hasSideEffects).toBeTruthy() + }) +}) diff --git a/packages/next/package.json b/packages/next/package.json index f6cd3ca769e..fed3cae52c3 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -13,7 +13,8 @@ "esm/*.js", "lib/*.js", "src/*.ts", - "*.scss" + "*.scss", + "**/*/style.js" ], "repository": { "type": "git",