diff --git a/docs/guide/advanced/optimization.md b/docs/guide/advanced/optimization.md index ef9540e4f..0816fa3a7 100644 --- a/docs/guide/advanced/optimization.md +++ b/docs/guide/advanced/optimization.md @@ -227,6 +227,7 @@ the each time localization is performed in an application using `$t` or `t` func You need to configure the following feature flag with `esm-bundler` build and bundler such as vite: - `__INTLIFY_JIT_COMPILATION__` (enable/disable message compiler for JIT style, default: `false`) +- `__INTLIFY_DROP_MESSAGE_COMPILER__` (enable/disable whether to tree-shake message compiler when we will be bundling, this flag works when `__INTLIFY_JIT_COMPILATION__` is enabled. default: `false`) :::warning NOTICE This feature is opted out as default, because compatibility with previous version before v9.3. diff --git a/packages/core-base/src/compilation.ts b/packages/core-base/src/compilation.ts index 018047421..0f3f525d2 100644 --- a/packages/core-base/src/compilation.ts +++ b/packages/core-base/src/compilation.ts @@ -1,4 +1,4 @@ -import { warn, format, isBoolean, isString } from '@intlify/shared' +import { warn, format, isObject, isBoolean, isString } from '@intlify/shared' import { baseCompile as baseCompileCore, defaultOnError, @@ -31,6 +31,11 @@ export function clearCompileCache(): void { compileCache = Object.create(null) } +export const isMessageAST = (val: unknown): val is ResourceNode => + isObject(val) && + (val.t === 0 || val.type === 0) && + ('b' in val || 'body' in val) + function baseCompile( message: string, options: CompileOptions = {} @@ -101,7 +106,11 @@ export function compile< message: MessageSource, context: MessageCompilerContext ): MessageFunction { - if (isString(message)) { + if ( + __FEATURE_JIT_COMPILATION__ && + !__FEATURE_DROP_MESSAGE_COMPILER__ && + isString(message) + ) { // check HTML message const warnHtmlMessage = isBoolean(context.warnHtmlMessage) ? context.warnHtmlMessage @@ -131,6 +140,13 @@ export function compile< ? ((compileCache as MessageFunctions)[cacheKey] = msg) : msg } else { + if (__DEV__ && !isMessageAST(message)) { + warn( + `the message that is resolve with key '${context.key}') is not supported for jit compilation` + ) + return (() => message) as MessageFunction + } + // AST case (passed from bundler) const cacheKey = (message as unknown as ResourceNode).cacheKey if (cacheKey) { diff --git a/packages/core-base/src/misc.ts b/packages/core-base/src/misc.ts index f64a2fc17..88d9290d4 100644 --- a/packages/core-base/src/misc.ts +++ b/packages/core-base/src/misc.ts @@ -12,4 +12,8 @@ export function initFeatureFlags(): void { if (typeof __FEATURE_JIT_COMPILATION__ !== 'boolean') { getGlobalThis().__INTLIFY_JIT_COMPILATION__ = false } + + if (typeof __FEATURE_DROP_MESSAGE_COMPILER__ !== 'boolean') { + getGlobalThis().__INTLIFY_DROP_MESSAGE_COMPILER__ = false + } } diff --git a/packages/core-base/src/translate.ts b/packages/core-base/src/translate.ts index ba8fee107..6ca70b8ed 100644 --- a/packages/core-base/src/translate.ts +++ b/packages/core-base/src/translate.ts @@ -16,6 +16,7 @@ import { assign, isObject } from '@intlify/shared' +import { isMessageAST } from './compilation' import { createMessageContext } from './runtime' import { isTranslateFallbackWarn, @@ -51,12 +52,10 @@ import type { import type { PickupKeys } from './types' const NOOP_MESSAGE_FUNCTION = () => '' + export const isMessageFunction = (val: unknown): val is MessageFunction => isFunction(val) -export const isMessageAST = (val: unknown): val is ResourceNode => - isObject(val) && val.type === 0 && ('body' in val || 'b' in val) - /** * # translate * diff --git a/packages/core-base/test/compilation.test.ts b/packages/core-base/test/compilation.test.ts index 4081d50ef..7aa3df8d8 100644 --- a/packages/core-base/test/compilation.test.ts +++ b/packages/core-base/test/compilation.test.ts @@ -2,6 +2,7 @@ import { baseCompile } from '@intlify/message-compiler' import { compileToFunction, compile, + isMessageAST, clearCompileCache } from '../src/compilation' import { createMessageContext as context } from '../src/runtime' @@ -12,6 +13,26 @@ beforeAll(() => { clearCompileCache() }) +describe('isMessageAST', () => { + describe('basic AST', () => { + test('should be true', () => { + expect(isMessageAST({ type: 0, body: '' })).toBe(true) + }) + }) + + describe('minify AST', () => { + test('should be true', () => { + expect(isMessageAST({ type: 0, b: '' })).toBe(true) + }) + }) + + describe('not message compiler AST format', () => { + test('should be false', () => { + expect(isMessageAST({ b: '' })).toBe(false) + }) + }) +}) + describe('compileToFunction', () => { test('basic', () => { const msg = compileToFunction('hello {name}!', DEFAULT_CONTEXT) diff --git a/packages/core-base/test/translate.test.ts b/packages/core-base/test/translate.test.ts index e8563bb25..58a239eaa 100644 --- a/packages/core-base/test/translate.test.ts +++ b/packages/core-base/test/translate.test.ts @@ -13,7 +13,7 @@ vi.mock('@intlify/shared', async () => { }) import { createCoreContext as context, NOT_REOSLVED } from '../src/context' -import { translate, isMessageAST } from '../src/translate' +import { translate } from '../src/translate' import { CoreErrorCodes, errorMessages } from '../src/errors' import { registerMessageCompiler, @@ -991,25 +991,3 @@ describe('AST passing', () => { expect(translate(ctx, 'hi')).toEqual('hi kazupon !') }) }) - -describe('isMessageAST', () => { - describe('basic AST', () => { - test('should be true', () => { - expect(isMessageAST({ type: 0, body: '' })).toBe(true) - }) - }) - - describe('minify AST', () => { - test('should be true', () => { - expect(isMessageAST({ type: 0, b: '' })).toBe(true) - }) - }) - - describe('not message compiler AST format', () => { - test('should be false', () => { - expect(isMessageAST({ b: '' })).toBe(false) - }) - }) -}) - -/* eslint-enable @typescript-eslint/no-empty-function, @typescript-eslint/no-explicit-any */ diff --git a/packages/global.d.ts b/packages/global.d.ts index 9a071f7b5..1ad88252f 100644 --- a/packages/global.d.ts +++ b/packages/global.d.ts @@ -18,3 +18,4 @@ declare let __FEATURE_PROD_INTLIFY_DEVTOOLS__: boolean declare let __FEATURE_LEGACY_API__: boolean declare let __FEATURE_FULL_INSTALL__: boolean declare let __FEATURE_JIT_COMPILATION__: boolean +declare let __FEATURE_DROP_MESSAGE_COMPILER__: boolean diff --git a/packages/size-check-core/vite.config.ts b/packages/size-check-core/vite.config.ts index ddca80aef..19bb449dd 100644 --- a/packages/size-check-core/vite.config.ts +++ b/packages/size-check-core/vite.config.ts @@ -13,9 +13,10 @@ export default defineConfig({ __RUNTIME__: true, // is targeting Node (SSR)? __NODE_JS__: false, - 'process.env.NODE_ENV': JSON.stringify('production'), - __INTLIFY_JIT_COMPILATION__: true, - __INTLIFY_PROD_DEVTOOLS__: false + __INTLIFY_JIT_COMPILATION__: false, + __INTLIFY_DROP_MESSAGE_COMPILER__: false, + __INTLIFY_PROD_DEVTOOLS__: false, + 'process.env.NODE_ENV': JSON.stringify('production') }, resolve: { alias: { diff --git a/packages/size-check-petite-vue-i18n/vite.config.ts b/packages/size-check-petite-vue-i18n/vite.config.ts index 6aa3d688b..cb950118e 100644 --- a/packages/size-check-petite-vue-i18n/vite.config.ts +++ b/packages/size-check-petite-vue-i18n/vite.config.ts @@ -18,7 +18,8 @@ export default defineConfig({ __VUE_I18N_LEGACY_API__: false, __VUE_I18N_FULL_INSTALL__: false, __VUE_PROD_DEVTOOLS__: false, - // __INTLIFY_JIT_COMPILATION__: true, + __INTLIFY_JIT_COMPILATION__: true, + __INTLIFY_DROP_MESSAGE_COMPILER__: true, __INTLIFY_PROD_DEVTOOLS__: false, 'process.env.NODE_ENV': JSON.stringify('production') }, @@ -28,6 +29,7 @@ export default defineConfig({ } }, build: { + minify: false, rollupOptions: { output: { entryFileNames: `assets/[name].js`, diff --git a/packages/size-check-vue-i18n/vite.config.ts b/packages/size-check-vue-i18n/vite.config.ts index afa76693a..0eee88ac3 100644 --- a/packages/size-check-vue-i18n/vite.config.ts +++ b/packages/size-check-vue-i18n/vite.config.ts @@ -19,6 +19,7 @@ export default defineConfig({ __VUE_I18N_FULL_INSTALL__: false, __VUE_PROD_DEVTOOLS__: false, __INTLIFY_JIT_COMPILATION__: true, + __INTLIFY_DROP_MESSAGE_COMPILER__: true, __INTLIFY_PROD_DEVTOOLS__: false, 'process.env.NODE_ENV': JSON.stringify('production') // 'process.env.NODE_ENV': JSON.stringify('development') diff --git a/packages/vue-i18n-core/src/misc.ts b/packages/vue-i18n-core/src/misc.ts index c1464b2bf..3a2d49e05 100644 --- a/packages/vue-i18n-core/src/misc.ts +++ b/packages/vue-i18n-core/src/misc.ts @@ -27,6 +27,10 @@ export function initFeatureFlags(): void { getGlobalThis().__INTLIFY_JIT_COMPILATION__ = false } + if (typeof __FEATURE_DROP_MESSAGE_COMPILER__ !== 'boolean') { + getGlobalThis().__INTLIFY_DROP_MESSAGE_COMPILER__ = false + } + if (typeof __FEATURE_PROD_INTLIFY_DEVTOOLS__ !== 'boolean') { getGlobalThis().__INTLIFY_PROD_DEVTOOLS__ = false } diff --git a/packages/vue-i18n/README.md b/packages/vue-i18n/README.md index f4f4dcbf7..c7b0de1c2 100644 --- a/packages/vue-i18n/README.md +++ b/packages/vue-i18n/README.md @@ -52,8 +52,9 @@ The `esm-bundler` builds now exposes global feature flags that can be overwritte - `__VUE_I18N_FULL_INSTALL__` (enable/disable, in addition to vue-i18n APIs, components and directives all fully support installation: `true`) - `__VUE_I18N_LEGACY_API__` (enable/disable vue-i18n legacy style APIs support, default: `true`) - `__INTLIFY_JIT_COMPILATION__` (enable/disable message compiler for JIT style, default: `false`) +- `__INTLIFY_DROP_MESSAGE_COMPILER__` (enable/disable whether to tree-shake message compiler when we will be bundling, this flag works when `__INTLIFY_JIT_COMPILATION__` is enabled. default: `false`) -> NOTE: `__INTLIFY_JIT_COMPILATION__` flag support version, 9.3+ +> NOTE: `__INTLIFY_JIT_COMPILATION__`, `__INTLIFY_DROP_MESSAGE_COMPILER__` flag support version, 9.3+ The build will work without configuring these flags, however it is **strongly recommended** to properly configure them in order to get proper tree shaking in the final bundle. To configure these flags: diff --git a/rollup.config.mjs b/rollup.config.mjs index 254d4462f..20d145b64 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -358,6 +358,9 @@ function createReplacePlugin( __FEATURE_JIT_COMPILATION__: isBundlerESMBuild ? `__INTLIFY_JIT_COMPILATION__` : `false`, + __FEATURE_DROP_MESSAGE_COMPILER__: isBundlerESMBuild + ? `__INTLIFY_DROP_MESSAGE_COMPILER__` + : `false`, ...(isProduction && isBrowserBuild ? { 'emitError(': `/*#__PURE__*/ emitError(`, diff --git a/vitest.config.ts b/vitest.config.ts index 433425c25..bb87f6295 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -17,7 +17,9 @@ export default defineConfig({ __LITE__: false, __BRIDGE__: false, __FEATURE_FULL_INSTALL__: true, - __FEATURE_LEGACY_API__: true + __FEATURE_LEGACY_API__: true, + __FEATURE_JIT_COMPILATION__: true, + __FEATURE_DROP_MESSAGE_COMPILER__: false }, resolve: { alias: entries