@u27n/webpack

1.0.0 • Public • Published

U27N Webpack Plugin

This is a webpack plugin that integrates the u27n toolchain into webpack as an alternative for the u27n cli.

Content


Setup

Add the u27n plugin to your webpack config:

const { U27nPlugin } = require("@u27n/webpack");

module.exports = {
  plugins: [
    new U27nPlugin({
      // Example options:
      config: "./u27n.json",
    })
  ]
}
  • config <string | string[]> - Filename of one or more u27n configs.
    • This can be relative to the webpack context.
    • Default is "./u27n.json"
  • env <string> - Absolute path to the environment implementation module.
  • output <string> - The filename template to output compiled locale data.
    • The following placeholders are supported:
      • "[hash]" - The content hash.
      • "[chunk]" - The webpack chunk id.
      • "[locale]" - The locale code.
    • Defaults are:
      • "locale/[hash].json" in production mode
      • "locale/[chunk]-[locale]" in development mode
  • modify and delay - Same as the CLI's --modify and --delay arguments.

At runtime, the u27n controller has to be globally registered:

import { U27N, Context, defaultLocaleFactory } from "@u27n/core/runtime";
import { registerController } from "@u27n/webpack/runtime";

const u27n = new U27N({
  localeFactory: defaultLocaleFactory,
});

registerController(u27n);

// After registration, the locale may be set:
await u27n.setLocaleAuto(["en", "de"]);

const context = new Context(u27n, "example", "en");

export const t = context.t;

Note, that other u27n clients can be removed.


Dynamic Imports

When dynamic imports are used, locale data is split up into chunks.

When invoking a dynamic import, locale data for the imported modules is loaded automatically:

// index.ts
(await import("./page")).show();

// page.ts
export function show() {
  console.log(t("Hello World!"));
}

When switching locales, locale data is loaded for all previously imported modules. When a dynamically imported module is no longer needed, you should prevent loading locale data for that module until it is imported again:

import { forgetModule } from "@u27n/webpack/runtime";

const page = await import("./page");
// Do something with page...

// When page is no longer needed:
forgetModule(page);

Environments

By default, fetch is used to request locale chunks relative to webpack's public path:

new U27nPlugin({
  // This is the default environment:
  env: U27nPlugin.ENV_FETCH,
})

NodeJS

The ENV_NODE environment uses node:fs/promises to read locale chunks from disk:

new U27nPlugin({
  env: U27nPlugin.ENV_NODE,
})

Custom Environments

If further customization is needed, you can implement your own environment module as specified in src/runtime/env/module-proxy.d.ts.

// /u27n-environment.js
export const env = {
  async fetchLocaleChunk(name) {
    const response = await fetch(__webpack_public_path__ + name);
    if (response.ok) {
      return response.json();
    }
    throw new Error(`Failed to fetch locale chunk: ${JSON.stringify(name)}`);
  },
};
new U27nPlugin({
  env: require.resolve("./u27n-environment.js"),
})

Multiple Controllers

To implement things like server side rendering, multiple controllers can be registered:

function createLocale(locale) {
  const u27n = new U27N({
    localeFactory: defaultLocaleFactory,
  });

  registerController(u27n);
  await u27n.setLocale(locale);

  return new Context(u27n, "example", "en").t;
}

const en = await createLocale("en");
const de = await createLocale("de");

Caching

Loaded locale chunks are cached forever by default. In development, it can be useful to clear this cache manually to allow loading updated locale data:

import { clearCache } from "@u27n/webpack/runtime";

if (u27n.locale) {
  clearCache();
  await u27n.setLocale(u27n.locale.code);
}

Troubleshooting

  • Loading locale data causes errors:
    • If ENV_FETCH is used, check that locale data from the output directory is available under webpack's public path.
    • If ENV_NODE is used, check that the runtime is bundled in a chunk file that is located in the root output directory.
      • If this is not possible for some reason, consider implementing your own environment module that compensates for custom paths.
  • Some parts of the application are not translated or changing locales throws errors:
    • Check the compiler output for diagnostics. Outdated translations are not included by default.
    • Check if the error is caused by custom environment implementation.
    • Temporarily disable hot module reloading.
    • Check your package-lock.json file if there are multiple @u27n/webpack packages installed.
      • In this case, webpack may bundle multiple conflicting runtimes which is not supported.
      • To resolve this issue, use npm overrides to use a single version of @u27n/webpack.
  • ReferenceError: _u27nw_i is not defined:
    • This happens if the u27n webpack runtime is not loaded before any dynamic imports are invoked.
    • To avoid this issue, make sure, that the @u27n/webpack/runtime module is imported in an entry chunk.

Internals

Note, that internals are only documented for transparency and are not considered stable API.

This plugin uses global variables prefixed with "_u27nw_".
For more information in globals, see src/types/runtime.d.ts.


Compatibility

The table below shows what core versions are supported by this package.

| @u27n/webpack | @u27n/core | |-|-|-| | 1.x | 3.x | | 0.x | 2.x |

Dependents (0)

Package Sidebar

Install

npm i @u27n/webpack

Weekly Downloads

1

Version

1.0.0

License

none

Unpacked Size

147 kB

Total Files

58

Last publish

Collaborators

  • mpt