/** * ## Barrel Optimizations * * This loader is used to optimize the imports of "barrel" files that have many * re-exports. Currently, both Node.js and Webpack have to enter all of these * submodules even if we only need a few of them. * * For example, say a file `foo.js` with the following contents: * * export { a } from './a' * export { b } from './b' * export { c } from './c' * ... * * If the user imports `a` only, this loader will accept the `names` option to * be `['a']`. Then, it request the "__barrel_transform__" SWC transform to load * `foo.js` and receive the following output: * * export const __next_private_export_map__ = '[["a","./a","a"],["b","./b","b"],["c","./c","c"],...]' * * format: '["", "", ""]' * e.g.: import { a as b } from './module-a' => '["b", "./module-a", "a"]' * * The export map, generated by SWC, is a JSON that represents the exports of * that module, their original file, and their original name (since you can do * `export { a as b }`). * * Then, this loader can safely remove all the exports that are not needed and * re-export the ones from `names`: * * export { a } from './a' * * That's the basic situation and also the happy path. * * * * ## Wildcard Exports * * For wildcard exports (e.g. `export * from './a'`), it becomes a bit more complicated. * Say `foo.js` with the following contents: * * export * from './a' * export * from './b' * export * from './c' * ... * * If the user imports `bar` from it, SWC can never know which files are going to be * exporting `bar`. So, we have to keep all the wildcard exports and do the same * process recursively. This loader will return the following output: * * export * from '__barrel_optimize__?names=bar&wildcard!=!./a' * export * from '__barrel_optimize__?names=bar&wildcard!=!./b' * export * from '__barrel_optimize__?names=bar&wildcard!=!./c' * ... * * The "!=!" tells Webpack to use the same loader to process './a', './b', and './c'. * After the recursive process, the "inner loaders" will either return an empty string * or: * * export * from './target' * * Where `target` is the file that exports `bar`. * * * * ## Non-Barrel Files * * If the file is not a barrel, we can't apply any optimizations. That's because * we can't easily remove things from the file. For example, say `foo.js` with: * * const v = 1 * export function b () { * return v * } * * If the user imports `b` only, we can't remove the `const v = 1` even though * the file is side-effect free. In these caes, this loader will simply re-export * `foo.js`: * * export * from './foo' * * Besides these cases, this loader also carefully handles the module cache so * SWC won't analyze the same file twice, and no instance of the same file will * be accidentally created as different instances. */ import type webpack from 'webpack'; declare const NextBarrelLoader: (this: webpack.LoaderContext<{ names: string[]; swcCacheDir: string; }>) => Promise; export default NextBarrelLoader;