Skip to content

Commit 28defaf

Browse files
authored
optimize tress-shaking supporting (#116)
1 parent f422b41 commit 28defaf

11 files changed

+71
-18
lines changed

.github/CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ The `build` script builds all build formats.
101101
- Does not ship a minified build (to be done together with the rest of the code after bundling)
102102
- For use with bundlers like `webpack`, `rollup` and `parcel`.
103103

104-
- **`esm`**:
104+
- **`esm-browser`**:
105105

106106
- For usage via native ES modules imports (in browser via `<script type="module">`, or via Node.js native ES modules support in the future)
107107
- Inlines all dependencies - i.e. it's a single ES module with no imports from other files
@@ -161,7 +161,7 @@ As a pure community-driven project without major corporate backing, we also welc
161161
- [Become a backer or sponsor on GitHub Sponsors](https://github.com/sponsors/kazupon)
162162
- [Become a backer or sponsor on Patreon](https://www.patreon.com/evanyou)
163163

164-
Funds donated via GitHub Sponsors and Patreon go to support kazuya kawaguchi full-time work on Intlify.
164+
Funds donated via GitHub Sponsors and Patreon go to support kazuya kawaguchi full-time work on Intlify.
165165

166166
## Credits
167167

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,42 @@ npm install --save vue-i18n@next
141141
yarn add vue-i18n@next
142142
```
143143

144+
## :package: About dist files
145+
146+
### From CDN or without a Bundler
147+
148+
- **`vue-i18n.global(.prod).js`**:
149+
- For direct use via `<script src="...">` in the browser. Exposes the `VueI18n` global.
150+
- Note that global builds are not [UMD](https://github.com/umdjs/umd) builds. They are built as [IIFEs](https://developer.mozilla.org/en-US/docs/Glossary/IIFE) and is only meant for direct use via `<script src="...">`.
151+
- Contains hard-coded prod/dev branches, and the prod build is pre-minified. Use the `*.prod.js` files for production.
152+
153+
- **`vue-i18n.esm-browser(.prod).js`**:
154+
- For usage via native ES modules imports (in browser via `<script type="module">`.
155+
- Shares the same runtime compilation, dependency inlining and hard-coded prod/dev behavior with the global build.
156+
157+
### With a Bundler
158+
159+
- **`vue-i18n.esm-bundler.js`**:
160+
- For use with bundlers like `webpack`, `rollup` and `parcel`.
161+
- Leaves prod/dev branches with `process.env.NODE_ENV` guards (must be replaced by bundler)
162+
- Does not ship minified builds (to be done together with the rest of the code after bundling)
163+
164+
#### Bundler Build Feature Flags
165+
166+
Starting with 9.0.0-beta.2, `esm-bundler` builds now exposes global feature flags that can be overwritten at compile time:
167+
168+
- `__VUE_I18N_FULL_INSTALL__` (enable/disable, in addition to vue-i18n APIs, components and directives all fully support installation: `true`)
169+
- `__VUE_I18N_LEGACY_API__` (enable/disable vue-i18n legacy style APIs support, default: `true`)
170+
- `__INTLIFY_PROD_DEVTOOLS__` (enable/disable intlify-devtools and vue-devtools support in production, default: `false`)
171+
172+
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:
173+
174+
- webpack: use [DefinePlugin](https://webpack.js.org/plugins/define-plugin/)
175+
- Rollup: use [@rollup/plugin-replace](https://github.com/rollup/plugins/tree/master/packages/replace)
176+
- Vite: configured by default, but can be overwritten using the [`define` option](https://github.com/vitejs/vite/blob/a4133c073e640b17276b2de6e91a6857bdf382e1/src/node/config.ts#L72-L76)
177+
178+
Note: the replacement value **must be boolean literals** and cannot be strings, otherwise the bundler/minifier will not be able to properly evaluate the conditions.
179+
144180

145181
## :white_check_mark: TODOs
146182
<details>

jest.config.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ module.exports = {
6868
__GLOBAL__: false,
6969
__ESM_BUNDLER__: true,
7070
__ESM_BROWSER__: false,
71-
__NODE_JS__: true
71+
__NODE_JS__: true,
72+
__FEATURE_FULL_INSTALL__: true,
73+
__FEATURE_LEGACY_API__: true
7274
},
7375

7476
// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.

rollup.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,12 @@ function createReplacePlugin(
169169
__ESM_BROWSER__: isBrowserESMBuild,
170170
__NODE_JS__: isNodeBuild,
171171
// feature flags
172+
__FEATURE_FULL_INSTALL__: isBundlerESMBuild
173+
? `__VUE_I18N_FULL_INSTALL__`
174+
: true,
175+
__FEATURE_LEGACY_API__: isBundlerESMBuild
176+
? `__VUE_I18N_LEGACY_API__`
177+
: true,
172178
__FEATURE_PROD_DEVTOOLS__: isBundlerESMBuild
173179
? `__INTLIFY_PROD_DEVTOOLS__`
174180
: false,

src/errors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export function createI18nError(
3939
export const errorMessages: { [code: number]: string } = {
4040
[I18nErrorCodes.UNEXPECTED_RETURN_TYPE]: 'Unexpected return type in composer',
4141
[I18nErrorCodes.INVALID_ARGUMENT]: 'Invalid argument',
42-
[I18nErrorCodes.NOT_INSLALLED]: 'Need to install with use function',
42+
[I18nErrorCodes.NOT_INSLALLED]: 'Need to install with app.use function',
4343
[I18nErrorCodes.UNEXPECTED_ERROR]: 'Unexpeced error',
4444
[I18nErrorCodes.NOT_AVAILABLE_IN_LEGACY_MODE]: 'Not available in legacy mode',
4545
[I18nErrorCodes.REQUIRED_VALUE]: `Required in value: {0}`,

src/global.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ declare let __VERSION__: string
77

88
// Feature flags
99
declare let __FEATURE_PROD_DEVTOOLS__: boolean
10+
declare let __FEATURE_LEGACY_API__: boolean
11+
declare let __FEATURE_FULL_INSTALL__: boolean

src/i18n.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,16 @@ export function createI18n<
259259
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
260260
app.__VUE_I18N__ = i18n as I18n & I18nInternal
261261
}
262+
263+
// setup global provider
262264
app.__VUE_I18N_SYMBOL__ = symbol
263-
apply<Messages, DateTimeFormats, NumberFormats>(app, i18n, ...options)
264-
if (__legacyMode) {
265+
app.provide(app.__VUE_I18N_SYMBOL__, i18n)
266+
267+
if (__FEATURE_FULL_INSTALL__) {
268+
apply<Messages, DateTimeFormats, NumberFormats>(app, i18n, ...options)
269+
}
270+
271+
if (__FEATURE_LEGACY_API__ && __legacyMode) {
265272
app.mixin(
266273
defineMixin<Messages, DateTimeFormats, NumberFormats>(
267274
__global as VueI18n<Messages, DateTimeFormats, NumberFormats>,

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export {
5858
BaseFormatProps,
5959
ComponetI18nScope
6060
} from './components'
61+
export { vTDirective } from './directive'
6162
export { I18nPluginOptions } from './plugin'
6263
export { VERSION } from './misc'
6364

src/misc.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ export const VERSION = __VERSION__
1010
export function initFeatureFlags(): void {
1111
let needWarn = false
1212

13+
if (typeof __FEATURE_FULL_INSTALL__ !== 'boolean') {
14+
needWarn = true
15+
getGlobalThis().__VUE_I18N_FULL_INSTALL__ = true
16+
}
17+
18+
if (typeof __FEATURE_LEGACY_API__ !== 'boolean') {
19+
needWarn = true
20+
getGlobalThis().__VUE_I18N_LEGACY_API__ = true
21+
}
22+
1323
if (typeof __FEATURE_PROD_DEVTOOLS__ !== 'boolean') {
1424
needWarn = true
1525
getGlobalThis().__INTLIFY_PROD_DEVTOOLS__ = false
@@ -36,7 +46,7 @@ export function initDev(): void {
3646

3747
if (__BROWSER__) {
3848
console.info(
39-
`You are running a development build of Vue.\n` +
49+
`You are running a development build of vue-i18n.\n` +
4050
`Make sure to use the production build (*.prod.js) when deploying for production.`
4151
)
4252
}

src/plugin.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { App, Component } from 'vue'
22
import { I18n } from './i18n'
33
import { Translation, NumberFormat, DatetimeFormat } from './components'
44
import { vTDirective } from './directive'
5-
import { I18nErrorCodes, createI18nError } from './errors'
65
import { I18nWarnCodes, getWarnMessage } from './warnings'
76
import { isPlainObject, warn, isBoolean } from './utils'
87

@@ -53,10 +52,4 @@ export function apply<Messages, DateTimeFormats, NumberFormats>(
5352
't',
5453
vTDirective<Messages, DateTimeFormats, NumberFormats>(i18n)
5554
)
56-
57-
// setup global provider
58-
if (!app.__VUE_I18N_SYMBOL__) {
59-
throw createI18nError(I18nErrorCodes.UNEXPECTED_ERROR)
60-
}
61-
app.provide(app.__VUE_I18N_SYMBOL__, i18n)
6255
}

test/plugin.test.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ describe('useI18nComponentName option', () => {
2121
mockWarn.mockImplementation(() => {})
2222

2323
const app = createApp({})
24-
app.__VUE_I18N_SYMBOL__ = Symbol()
2524
const i18n = {} as I18n & I18nInternal
2625

2726
apply(app, i18n)
@@ -33,7 +32,6 @@ describe('useI18nComponentName option', () => {
3332
mockWarn.mockImplementation(() => {})
3433

3534
const app = createApp({})
36-
app.__VUE_I18N_SYMBOL__ = Symbol()
3735
const i18n = {} as I18n & I18nInternal
3836

3937
apply(app, i18n, { useI18nComponentName: true })
@@ -49,7 +47,6 @@ describe('useI18nComponentName option', () => {
4947
describe('globalInstall option', () => {
5048
test('default', () => {
5149
const app = createApp({})
52-
app.__VUE_I18N_SYMBOL__ = Symbol()
5350
const i18n = {} as I18n & I18nInternal
5451
const spy = jest.spyOn(app, 'component')
5552

@@ -59,7 +56,6 @@ describe('globalInstall option', () => {
5956

6057
test('false', () => {
6158
const app = createApp({})
62-
app.__VUE_I18N_SYMBOL__ = Symbol()
6359
const i18n = {} as I18n & I18nInternal
6460
const spy = jest.spyOn(app, 'component')
6561

0 commit comments

Comments
 (0)