Skip to content

Commit 4503796

Browse files
authored
feat: hash file imports (#3376)
1 parent 4a8d7d5 commit 4503796

18 files changed

Lines changed: 663 additions & 816 deletions

specs/helper.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,14 @@ export async function startServerWithRuntimeConfig(env: Record<string, unknown>)
220220
await startServer(converted)
221221
return async () => startServer()
222222
}
223+
224+
export async function localeLoaderHelpers() {
225+
const ctx = useTestContext()
226+
const opts = await import(ctx.nuxt?.options.buildDir + '/i18n.options.mjs')
227+
228+
function findKey(code: string, ext: string, cache: boolean = false): string {
229+
return opts.localeLoaders[code].find(x => x.cache === cache && x.key.includes(ext + '_'))!.key
230+
}
231+
232+
return { findKey }
233+
}

specs/lazy_load/basic_lazy_load.spec.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { test, expect, describe } from 'vitest'
22
import { fileURLToPath } from 'node:url'
33
import { setup, url, $fetch } from '../utils'
4-
import { getText, getData, waitForMs, renderPage, waitForURL, getDom } from '../helper'
4+
import { getText, getData, waitForMs, renderPage, waitForURL, getDom, localeLoaderHelpers } from '../helper'
55

66
describe('basic lazy loading', async () => {
77
await setup({
@@ -115,19 +115,21 @@ describe('basic lazy loading', async () => {
115115
})
116116

117117
test('files with cache disabled bypass caching', async () => {
118-
const { page, consoleLogs } = await renderPage('/')
118+
const { page, consoleLogs: logs } = await renderPage('/')
119+
120+
const { findKey } = await localeLoaderHelpers()
119121

120122
await page.click('#lang-switcher-with-nuxt-link-en-GB')
121-
expect([...consoleLogs].filter(log => log.text.includes('lazy-locale-en-GB.js bypassing cache!'))).toHaveLength(1)
123+
expect(logs.filter(log => log.text.includes(`${findKey('en-GB', 'js')} bypassing cache!`))).toHaveLength(1)
122124

123125
await page.click('#lang-switcher-with-nuxt-link-fr')
124-
expect([...consoleLogs].filter(log => log.text.includes('lazy-locale-fr.json5 bypassing cache!'))).toHaveLength(1)
126+
expect(logs.filter(log => log.text.includes(`${findKey('fr', 'json5')} bypassing cache!`))).toHaveLength(1)
125127

126128
await page.click('#lang-switcher-with-nuxt-link-en-GB')
127-
expect([...consoleLogs].filter(log => log.text.includes('lazy-locale-en-GB.js bypassing cache!'))).toHaveLength(2)
129+
expect(logs.filter(log => log.text.includes(`${findKey('en-GB', 'js')} bypassing cache!`))).toHaveLength(2)
128130

129131
await page.click('#lang-switcher-with-nuxt-link-fr')
130-
expect([...consoleLogs].filter(log => log.text.includes('lazy-locale-fr.json5 bypassing cache!'))).toHaveLength(2)
132+
expect(logs.filter(log => log.text.includes(`${findKey('fr', 'json5')} bypassing cache!`))).toHaveLength(2)
131133
})
132134

133135
test('manually loaded messages can be used in translations', async () => {

specs/lazy_load/restructure.spec.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { test, expect, describe } from 'vitest'
22
import { fileURLToPath } from 'node:url'
33
import { setup, url } from '../utils'
4-
import { getText, getData, waitForMs, renderPage, waitForURL } from '../helper'
4+
import { getText, getData, waitForMs, renderPage, waitForURL, localeLoaderHelpers } from '../helper'
55

66
describe('basic lazy loading (restructure)', async () => {
77
await setup({
@@ -115,19 +115,21 @@ describe('basic lazy loading (restructure)', async () => {
115115
})
116116

117117
test('files with cache disabled bypass caching', async () => {
118-
const { page, consoleLogs } = await renderPage('/')
118+
const { page, consoleLogs: logs } = await renderPage('/')
119+
120+
const { findKey } = await localeLoaderHelpers()
119121

120122
await page.click('#lang-switcher-with-nuxt-link-en-GB')
121-
expect([...consoleLogs].filter(log => log.text.includes('lazy-locale-en-GB.js bypassing cache!'))).toHaveLength(1)
123+
expect(logs.filter(log => log.text.includes(`${findKey('en-GB', 'js')} bypassing cache!`))).toHaveLength(1)
122124

123125
await page.click('#lang-switcher-with-nuxt-link-fr')
124-
expect([...consoleLogs].filter(log => log.text.includes('lazy-locale-fr.json5 bypassing cache!'))).toHaveLength(1)
126+
expect(logs.filter(log => log.text.includes(`${findKey('fr', 'json5')} bypassing cache!`))).toHaveLength(1)
125127

126128
await page.click('#lang-switcher-with-nuxt-link-en-GB')
127-
expect([...consoleLogs].filter(log => log.text.includes('lazy-locale-en-GB.js bypassing cache!'))).toHaveLength(2)
129+
expect(logs.filter(log => log.text.includes(`${findKey('en-GB', 'js')} bypassing cache!`))).toHaveLength(2)
128130

129131
await page.click('#lang-switcher-with-nuxt-link-fr')
130-
expect([...consoleLogs].filter(log => log.text.includes('lazy-locale-fr.json5 bypassing cache!'))).toHaveLength(2)
132+
expect(logs.filter(log => log.text.includes(`${findKey('fr', 'json5')} bypassing cache!`))).toHaveLength(2)
131133
})
132134

133135
test('manually loaded messages can be used in translations', async () => {

specs/ssg/basic_lazy_load.spec.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { test, expect, describe } from 'vitest'
22
import { fileURLToPath } from 'node:url'
3-
import { setup, url } from '../utils'
4-
import { getText, getData, waitForMs, renderPage, waitForURL } from '../helper'
3+
import { setup, url, useTestContext } from '../utils'
4+
import { getText, getData, waitForMs, renderPage, waitForURL, localeLoaderHelpers } from '../helper'
55

66
describe('basic lazy loading', async () => {
77
await setup({
@@ -116,19 +116,21 @@ describe('basic lazy loading', async () => {
116116
})
117117

118118
test('files with cache disabled bypass caching', async () => {
119-
const { page, consoleLogs } = await renderPage('/')
119+
const { page, consoleLogs: logs } = await renderPage('/')
120+
121+
const { findKey } = await localeLoaderHelpers()
120122

121123
await page.click('#lang-switcher-with-nuxt-link-en-GB')
122-
expect([...consoleLogs].filter(log => log.text.includes('lazy-locale-en-GB.js bypassing cache!'))).toHaveLength(1)
124+
expect(logs.filter(log => log.text.includes(`${findKey('en-GB', 'js')} bypassing cache!`))).toHaveLength(1)
123125

124126
await page.click('#lang-switcher-with-nuxt-link-fr')
125-
expect([...consoleLogs].filter(log => log.text.includes('lazy-locale-fr.json5 bypassing cache!'))).toHaveLength(1)
127+
expect(logs.filter(log => log.text.includes(`${findKey('fr', 'json5')} bypassing cache!`))).toHaveLength(1)
126128

127129
await page.click('#lang-switcher-with-nuxt-link-en-GB')
128-
expect([...consoleLogs].filter(log => log.text.includes('lazy-locale-en-GB.js bypassing cache!'))).toHaveLength(2)
130+
expect(logs.filter(log => log.text.includes(`${findKey('en-GB', 'js')} bypassing cache!`))).toHaveLength(2)
129131

130132
await page.click('#lang-switcher-with-nuxt-link-fr')
131-
expect([...consoleLogs].filter(log => log.text.includes('lazy-locale-fr.json5 bypassing cache!'))).toHaveLength(2)
133+
expect(logs.filter(log => log.text.includes(`${findKey('fr', 'json5')} bypassing cache!`))).toHaveLength(2)
132134
})
133135

134136
test('manually loaded messages can be used in translations', async () => {

src/bundler.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
/* eslint-disable @typescript-eslint/no-floating-promises */
12
import createDebug from 'debug'
23
import { resolve } from 'pathe'
34
import { extendViteConfig, addWebpackPlugin, addBuildPlugin } from '@nuxt/kit'
45
import VueI18nPlugin from '@intlify/unplugin-vue-i18n'
6+
import { toArray } from './utils'
57
import { TransformMacroPlugin } from './transform/macros'
68
import { ResourcePlugin } from './transform/resource'
9+
import { i18nVirtualLoggerPlugin } from './virtual-logger'
710
import { TransformI18nFunctionPlugin } from './transform/i18n-function-injection'
811
import { getLayerLangPaths } from './layers'
912

@@ -14,7 +17,8 @@ import type { I18nNuxtContext } from './context'
1417

1518
const debug = createDebug('@nuxtjs/i18n:bundler')
1619

17-
export async function extendBundler({ options: nuxtOptions }: I18nNuxtContext, nuxt: Nuxt) {
20+
export async function extendBundler(ctx: I18nNuxtContext, nuxt: Nuxt) {
21+
const { options: nuxtOptions } = ctx
1822
const langPaths = getLayerLangPaths(nuxt)
1923
debug('langPaths -', langPaths)
2024
const i18nModulePaths =
@@ -27,6 +31,26 @@ export async function extendBundler({ options: nuxtOptions }: I18nNuxtContext, n
2731
sourcemap: !!nuxt.options.sourcemap.server || !!nuxt.options.sourcemap.client
2832
}
2933

34+
/**
35+
* shared plugins (nuxt/nitro)
36+
*/
37+
const loggerPlugin = i18nVirtualLoggerPlugin(ctx.options.debug)
38+
const resourcePlugin = ResourcePlugin(sourceMapOptions, ctx)
39+
40+
addBuildPlugin(loggerPlugin)
41+
addBuildPlugin(resourcePlugin)
42+
43+
nuxt.hook('nitro:config', async cfg => {
44+
cfg.rollupConfig!.plugins = (await cfg.rollupConfig!.plugins) || []
45+
cfg.rollupConfig!.plugins = toArray(cfg.rollupConfig!.plugins)
46+
47+
cfg.rollupConfig!.plugins.push(loggerPlugin.rollup())
48+
cfg.rollupConfig!.plugins.push(resourcePlugin.rollup())
49+
})
50+
51+
/**
52+
* shared plugins (webpack/vite)
53+
*/
3054
const vueI18nPluginOptions: PluginOptions = {
3155
allowDynamic: true,
3256
include: localeIncludePaths,
@@ -41,16 +65,11 @@ export async function extendBundler({ options: nuxtOptions }: I18nNuxtContext, n
4165
dropMessageCompiler: nuxtOptions.bundle.dropMessageCompiler,
4266
optimizeTranslationDirective: nuxtOptions.bundle.optimizeTranslationDirective
4367
}
44-
45-
/**
46-
* shared plugins
47-
*/
4868
addBuildPlugin({
4969
vite: () => VueI18nPlugin.vite(vueI18nPluginOptions),
5070
webpack: () => VueI18nPlugin.webpack(vueI18nPluginOptions)
5171
})
5272
addBuildPlugin(TransformMacroPlugin(sourceMapOptions))
53-
addBuildPlugin(ResourcePlugin(sourceMapOptions))
5473
if (nuxtOptions.experimental.autoImportTranslationFunctions) {
5574
addBuildPlugin(TransformI18nFunctionPlugin(sourceMapOptions))
5675
}

src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ export const NUXT_I18N_COMPOSABLE_DEFINE_ROUTE = 'defineI18nRoute'
8989
export const NUXT_I18N_COMPOSABLE_DEFINE_LOCALE = 'defineI18nLocale'
9090
export const NUXT_I18N_COMPOSABLE_DEFINE_CONFIG = 'defineI18nConfig'
9191
export const NUXT_I18N_COMPOSABLE_DEFINE_LOCALE_DETECTOR = 'defineI18nLocaleDetector'
92+
export const NUXT_I18N_VIRTUAL_PREFIX = 'virtual:nuxt-i18n'
9293

9394
export const TS_EXTENSIONS = ['.ts', '.cts', '.mts']
9495
export const JS_EXTENSIONS = ['.js', '.cjs', '.mjs']

src/context.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export interface I18nNuxtContext {
1717
isSSG: boolean
1818
isBuild: boolean
1919
isTest: boolean
20-
genTemplate: (isServer: boolean, lazy?: boolean) => string
20+
pages: boolean
2121
normalizedLocales: LocaleObject<string>[]
2222
localeCodes: string[]
2323
localeInfo: LocaleInfo[]
@@ -42,7 +42,11 @@ export function createContext(userOptions: NuxtI18nOptions, nuxt: Nuxt): I18nNux
4242
isSSG: nuxt.options._generate,
4343
isBuild: nuxt.options._build,
4444
isTest: nuxt.options.test,
45-
genTemplate: undefined!,
45+
// pages is initially undefined - has correct value when writing i18n.options template
46+
get pages() {
47+
// @ts-expect-error
48+
return nuxt.options.pages === true || (nuxt.options.pages && nuxt.options.pages?.enabled === true)
49+
},
4650
normalizedLocales: undefined!,
4751
localeCodes: undefined!,
4852
localeInfo: undefined!,

0 commit comments

Comments
 (0)