Skip to content

Commit

Permalink
optimize tress-shaking supporting (#116)
Browse files Browse the repository at this point in the history
  • Loading branch information
kazupon authored Sep 17, 2020
1 parent f422b41 commit 28defaf
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 18 deletions.
4 changes: 2 additions & 2 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ The `build` script builds all build formats.
- Does not ship a minified build (to be done together with the rest of the code after bundling)
- For use with bundlers like `webpack`, `rollup` and `parcel`.

- **`esm`**:
- **`esm-browser`**:

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

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

## Credits

Expand Down
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,42 @@ npm install --save vue-i18n@next
yarn add vue-i18n@next
```

## :package: About dist files

### From CDN or without a Bundler

- **`vue-i18n.global(.prod).js`**:
- For direct use via `<script src="...">` in the browser. Exposes the `VueI18n` global.
- 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="...">`.
- Contains hard-coded prod/dev branches, and the prod build is pre-minified. Use the `*.prod.js` files for production.

- **`vue-i18n.esm-browser(.prod).js`**:
- For usage via native ES modules imports (in browser via `<script type="module">`.
- Shares the same runtime compilation, dependency inlining and hard-coded prod/dev behavior with the global build.

### With a Bundler

- **`vue-i18n.esm-bundler.js`**:
- For use with bundlers like `webpack`, `rollup` and `parcel`.
- Leaves prod/dev branches with `process.env.NODE_ENV` guards (must be replaced by bundler)
- Does not ship minified builds (to be done together with the rest of the code after bundling)

#### Bundler Build Feature Flags

Starting with 9.0.0-beta.2, `esm-bundler` builds now exposes global feature flags that can be overwritten at compile time:

- `__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_PROD_DEVTOOLS__` (enable/disable intlify-devtools and vue-devtools support in production, default: `false`)

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:

- webpack: use [DefinePlugin](https://webpack.js.org/plugins/define-plugin/)
- Rollup: use [@rollup/plugin-replace](https://github.com/rollup/plugins/tree/master/packages/replace)
- 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)

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.


## :white_check_mark: TODOs
<details>
Expand Down
4 changes: 3 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ module.exports = {
__GLOBAL__: false,
__ESM_BUNDLER__: true,
__ESM_BROWSER__: false,
__NODE_JS__: true
__NODE_JS__: true,
__FEATURE_FULL_INSTALL__: true,
__FEATURE_LEGACY_API__: true
},

// 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.
Expand Down
6 changes: 6 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,12 @@ function createReplacePlugin(
__ESM_BROWSER__: isBrowserESMBuild,
__NODE_JS__: isNodeBuild,
// feature flags
__FEATURE_FULL_INSTALL__: isBundlerESMBuild
? `__VUE_I18N_FULL_INSTALL__`
: true,
__FEATURE_LEGACY_API__: isBundlerESMBuild
? `__VUE_I18N_LEGACY_API__`
: true,
__FEATURE_PROD_DEVTOOLS__: isBundlerESMBuild
? `__INTLIFY_PROD_DEVTOOLS__`
: false,
Expand Down
2 changes: 1 addition & 1 deletion src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function createI18nError(
export const errorMessages: { [code: number]: string } = {
[I18nErrorCodes.UNEXPECTED_RETURN_TYPE]: 'Unexpected return type in composer',
[I18nErrorCodes.INVALID_ARGUMENT]: 'Invalid argument',
[I18nErrorCodes.NOT_INSLALLED]: 'Need to install with use function',
[I18nErrorCodes.NOT_INSLALLED]: 'Need to install with app.use function',
[I18nErrorCodes.UNEXPECTED_ERROR]: 'Unexpeced error',
[I18nErrorCodes.NOT_AVAILABLE_IN_LEGACY_MODE]: 'Not available in legacy mode',
[I18nErrorCodes.REQUIRED_VALUE]: `Required in value: {0}`,
Expand Down
2 changes: 2 additions & 0 deletions src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ declare let __VERSION__: string

// Feature flags
declare let __FEATURE_PROD_DEVTOOLS__: boolean
declare let __FEATURE_LEGACY_API__: boolean
declare let __FEATURE_FULL_INSTALL__: boolean
11 changes: 9 additions & 2 deletions src/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,16 @@ export function createI18n<
if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {
app.__VUE_I18N__ = i18n as I18n & I18nInternal
}

// setup global provider
app.__VUE_I18N_SYMBOL__ = symbol
apply<Messages, DateTimeFormats, NumberFormats>(app, i18n, ...options)
if (__legacyMode) {
app.provide(app.__VUE_I18N_SYMBOL__, i18n)

if (__FEATURE_FULL_INSTALL__) {
apply<Messages, DateTimeFormats, NumberFormats>(app, i18n, ...options)
}

if (__FEATURE_LEGACY_API__ && __legacyMode) {
app.mixin(
defineMixin<Messages, DateTimeFormats, NumberFormats>(
__global as VueI18n<Messages, DateTimeFormats, NumberFormats>,
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export {
BaseFormatProps,
ComponetI18nScope
} from './components'
export { vTDirective } from './directive'
export { I18nPluginOptions } from './plugin'
export { VERSION } from './misc'

Expand Down
12 changes: 11 additions & 1 deletion src/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ export const VERSION = __VERSION__
export function initFeatureFlags(): void {
let needWarn = false

if (typeof __FEATURE_FULL_INSTALL__ !== 'boolean') {
needWarn = true
getGlobalThis().__VUE_I18N_FULL_INSTALL__ = true
}

if (typeof __FEATURE_LEGACY_API__ !== 'boolean') {
needWarn = true
getGlobalThis().__VUE_I18N_LEGACY_API__ = true
}

if (typeof __FEATURE_PROD_DEVTOOLS__ !== 'boolean') {
needWarn = true
getGlobalThis().__INTLIFY_PROD_DEVTOOLS__ = false
Expand All @@ -36,7 +46,7 @@ export function initDev(): void {

if (__BROWSER__) {
console.info(
`You are running a development build of Vue.\n` +
`You are running a development build of vue-i18n.\n` +
`Make sure to use the production build (*.prod.js) when deploying for production.`
)
}
Expand Down
7 changes: 0 additions & 7 deletions src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { App, Component } from 'vue'
import { I18n } from './i18n'
import { Translation, NumberFormat, DatetimeFormat } from './components'
import { vTDirective } from './directive'
import { I18nErrorCodes, createI18nError } from './errors'
import { I18nWarnCodes, getWarnMessage } from './warnings'
import { isPlainObject, warn, isBoolean } from './utils'

Expand Down Expand Up @@ -53,10 +52,4 @@ export function apply<Messages, DateTimeFormats, NumberFormats>(
't',
vTDirective<Messages, DateTimeFormats, NumberFormats>(i18n)
)

// setup global provider
if (!app.__VUE_I18N_SYMBOL__) {
throw createI18nError(I18nErrorCodes.UNEXPECTED_ERROR)
}
app.provide(app.__VUE_I18N_SYMBOL__, i18n)
}
4 changes: 0 additions & 4 deletions test/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ describe('useI18nComponentName option', () => {
mockWarn.mockImplementation(() => {})

const app = createApp({})
app.__VUE_I18N_SYMBOL__ = Symbol()
const i18n = {} as I18n & I18nInternal

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

const app = createApp({})
app.__VUE_I18N_SYMBOL__ = Symbol()
const i18n = {} as I18n & I18nInternal

apply(app, i18n, { useI18nComponentName: true })
Expand All @@ -49,7 +47,6 @@ describe('useI18nComponentName option', () => {
describe('globalInstall option', () => {
test('default', () => {
const app = createApp({})
app.__VUE_I18N_SYMBOL__ = Symbol()
const i18n = {} as I18n & I18nInternal
const spy = jest.spyOn(app, 'component')

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

test('false', () => {
const app = createApp({})
app.__VUE_I18N_SYMBOL__ = Symbol()
const i18n = {} as I18n & I18nInternal
const spy = jest.spyOn(app, 'component')

Expand Down

0 comments on commit 28defaf

Please sign in to comment.