Skip to content

Commit

Permalink
fix: 403 load error and sync loading (#2048)
Browse files Browse the repository at this point in the history
* fix: 403 load error and sync loading

* add comment

* fix: sync loading
  • Loading branch information
kazupon authored May 8, 2023
1 parent a069f38 commit d1499b6
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 17 deletions.
20 changes: 15 additions & 5 deletions src/gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,14 @@ export function generateLoaderOptions(
const makeImportKey = (root: string, dir: string, base: string) =>
normalize(`${root ? `${root}/` : ''}${dir ? `${dir}/` : ''}${base}`)

function generateSyncImports(gen: string, absolutePath: string, type: LocaleType, relativePath?: string) {
function generateSyncImports(
gen: string,
absolutePath: string,
type: LocaleType,
localeCode: string,
hash: string,
relativePath?: string
) {
if (!relativePath) {
return gen
}
Expand All @@ -79,7 +86,11 @@ export function generateLoaderOptions(
const assertFormat = ext.slice(1)
const variableName = genSafeVariableName(`locale_${convertToImportId(key)}`)
gen += `${genImport(
genImportSpecifier(loadPath, ext, absolutePath, type),
genImportSpecifier(loadPath, ext, absolutePath, type, {
hash,
virtualId: NUXT_I18N_LOCALE_PROXY_ID,
query: { locale: localeCode }
}),
variableName,
assertFormat ? { assert: { type: assertFormat } } : {}
)}\n`
Expand Down Expand Up @@ -110,9 +121,8 @@ export function generateLoaderOptions(
* Generate locale synthetic imports
*/
for (const localeInfo of syncLocaleFiles) {
convertToPairs(localeInfo).forEach(({ path, type, file }) => {
// TODO: support hash
genCode = generateSyncImports(genCode, path, type, file)
convertToPairs(localeInfo).forEach(({ path, type, file, hash }) => {
genCode = generateSyncImports(genCode, path, type, localeInfo.code, hash, file)
})
}

Expand Down
55 changes: 43 additions & 12 deletions src/runtime/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -500,42 +500,73 @@ export function getDomainFromLocale(localeCode: Locale, locales: LocaleObject[],
console.warn(formatMessage('Could not find domain name for locale ' + localeCode))
}

async function evaluateCode(raw: Blob) {
const url = URL.createObjectURL(raw)
const code = await import(/* @vite-ignore */ url).then(m => m.default || m)
URL.revokeObjectURL(url)
return code
}

export async function precompileLocale(
locale: Locale,
messages: LocaleMessages<DefineLocaleMessage>,
hash: string = NULL_HASH
) {
await $fetch(NUXT_I18N_PRECOMPILE_ENDPOINT, {
const raw = await $fetch<Blob>(NUXT_I18N_PRECOMPILE_ENDPOINT, {
method: 'POST',
responseType: 'blob',
body: {
locale,
type: 'locale',
hash,
resource: messages
}
})
return await loadPrecompiledMessages(locale + '-' + hash + '.js', 'locale')
if (process.dev && process.client) {
/**
* NOTE:
* If code precompiled directly by dynamic import is loaded directly as well as on the server side,
* it will be routed on the server side when the request is received.
* To avoid this, use the code received by fetching the precompiled code.
*/
return evaluateCode(raw)
} else {
return await loadPrecompiledMessages(locale + '-' + hash + '.js', 'locale')
}
}

export async function precompileConfig(
messages: I18nOptions['messages'],
hash: string = NULL_HASH
): Promise<I18nOptions['messages']> {
if (messages != null) {
await $fetch(NUXT_I18N_PRECOMPILE_ENDPOINT, {
const raw = await $fetch<Blob>(NUXT_I18N_PRECOMPILE_ENDPOINT, {
method: 'POST',
responseType: 'blob',
body: {
type: 'config',
hash,
resource: getNeedPrecompileMessages(messages)
}
})

const precompiledMessages = (await loadPrecompiledMessages('config-' + hash + '.js', 'config')) as NonNullable<
I18nOptions['messages']
>
for (const [locale, message] of Object.entries(precompiledMessages)) {
deepCopy(message, messages[locale])
let precompiledMessages: I18nOptions['messages']
if (process.dev && process.client) {
/**
* NOTE:
* If code precompiled directly by dynamic import is loaded directly as well as on the server side,
* it will be routed on the server side when the request is received.
* To avoid this, use the code received by fetching the precompiled code.
*/
precompiledMessages = await evaluateCode(raw)
} else {
precompiledMessages = (await loadPrecompiledMessages('config-' + hash + '.js', 'config')) as NonNullable<
I18nOptions['messages']
>
}
if (precompiledMessages != null) {
for (const [locale, message] of Object.entries(precompiledMessages)) {
deepCopy(message, messages[locale])
}
}
}
return messages
Expand All @@ -551,12 +582,12 @@ async function loadPrecompiledMessages(id: string, type: 'locale' | 'config') {
if (process.env.prerender) { // for prerender
url = type === 'config' ? '../../../i18n/' + id : '../../../i18n/locales/' + id
} else if (process.dev) { // for dev mode
url = type === 'config' ? '/.nuxt/i18n/' + id : '/.nuxt/i18n/locales/' + id
url = type === 'config' ? '.nuxt/i18n/' + id : '.nuxt/i18n/locales/' + id
} else {
throw new Error(`'loadPrecompiledMessages' is used in invalid environment.`)
}
} else { // for client
url = type === 'config' ? '/.nuxt/i18n/' + id : '/.nuxt/i18n/locales/' + id
} else {
throw new Error(`'loadPrecompiledMessages' is used in invalid environment.`)
}

return await import(/* @vite-ignore */ url).then(m => m.default || m)
Expand Down

0 comments on commit d1499b6

Please sign in to comment.