diff --git a/CHANGELOG.md b/CHANGELOG.md index d54c615..a03833c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ * Adds module debug logs when in asset debug mode (`APOS_ASSET_DEBUG=1`). * Adds an option for disabling the module preload polyfill. * Adds support for `synthetic` entrypoints, that will only process the entrypoint `prologue`. +* Adds support for `Modules/...` alias for the public builds (Webpack BC). +* Our Vite alias plugin now throws with an useful error message when `Modules/` alias resolver fails. ### Fixes diff --git a/lib/internals.js b/lib/internals.js index 815f03a..24d3af3 100644 --- a/lib/internals.js +++ b/lib/internals.js @@ -945,6 +945,7 @@ module.exports = (self) => { const vite = await import('vite'); // The base public config const config = await vitePublicConfig({ + sourceRoot: self.buildRootSource, input: self.getBuildInputs('public') }); const postcssConfig = await self.getPostcssConfig(self.buildOptions, 'public'); diff --git a/lib/vite-apos-config.js b/lib/vite-apos-config.js index ba884c6..bf8699a 100644 --- a/lib/vite-apos-config.js +++ b/lib/vite-apos-config.js @@ -2,7 +2,7 @@ module.exports = async ({ sourceRoot, input }) => { const vue = await import('@vitejs/plugin-vue'); - const apos = await import('./vite-plugin-apostrophe-apos.mjs'); + const apos = await import('./vite-plugin-apostrophe-alias.mjs'); /** @type {import('vite').UserConfig} */ return { @@ -21,7 +21,10 @@ module.exports = async ({ } }, plugins: [ - apos.default({ sourceRoot }), + apos.default({ + id: 'apos', + sourceRoot + }), vue.default() ], build: { diff --git a/lib/vite-plugin-apostrophe-alias.mjs b/lib/vite-plugin-apostrophe-alias.mjs new file mode 100644 index 0000000..adf165a --- /dev/null +++ b/lib/vite-plugin-apostrophe-alias.mjs @@ -0,0 +1,66 @@ +import { join } from 'node:path'; + +/** + * Resolve `apos` and `public` builds alias `Modules/`. The `sourceRoot` option + * should be the absolute path to `apos-build/.../src` folder. + * The `id` option should be either `apos` or `src` depending on the build it's + * being used for (apos or public respectively). + * + * @param {{ id: 'src' | 'apos', sourceRoot: string }} options + * @returns {import('vite').Plugin} + */ +export default function VitePluginApos({ sourceRoot, id } = {}) { + if (!id) { + throw new Error('[vite-plugin-apostrophe-alias] `id` option is required.'); + } + if (!sourceRoot) { + throw new Error( + '[vite-plugin-apostrophe-alias] `sourceRoot` option is required.' + ); + } + const pluginOptions = { + id, + sourceRoot + }; + + return { + name: 'vite-plugin-apostrophe-alias', + + async resolveId(source, importer, options) { + if (!source.startsWith('Modules/')) { + return null; + } + const chunks = source.replace('Modules/', '').split('/'); + let moduleName = chunks.shift(); + if (moduleName.startsWith('@')) { + moduleName += '/' + chunks.shift(); + } + const absPath = join( + pluginOptions.sourceRoot, + moduleName, + pluginOptions.id, + ...chunks + ); + const resolved = await this.resolve( + absPath, + importer, + options + ); + if (!resolved) { + // For internal debugging purposes + this.warn( + `Resolve attempt failed: "${source}" -> "${absPath}"` + ); + // For user-facing error messages + this.error( + `Unable to resolve module source "${moduleName}/ui/${id}/${join(...chunks)}" ` + + `from alias "${source}".\n` + + 'Please be sure to use the correct alias path. ' + + 'For more information, see:\n' + + 'https://docs.apostrophecms.org/guide/vite.html#resolve-alias-errors' + ); + } + return resolved; + } + }; +} diff --git a/lib/vite-plugin-apostrophe-apos.mjs b/lib/vite-plugin-apostrophe-apos.mjs deleted file mode 100644 index f072d5f..0000000 --- a/lib/vite-plugin-apostrophe-apos.mjs +++ /dev/null @@ -1,29 +0,0 @@ -import path from 'path'; - -export default function VitePluginApos({ sourceRoot }) { - return { - name: 'vite-plugin-apostrophe', - async resolveId(source, importer, options) { - if (!source.startsWith('Modules/')) { - return null; - } - const chunks = source.replace('Modules/', '').split('/'); - let moduleName = chunks.shift(); - if (moduleName.startsWith('@')) { - moduleName += '/' + chunks.shift(); - } - const resolved = await this.resolve( - path.join(sourceRoot, moduleName, 'apos', ...chunks), - importer, - options - ); - if (!resolved) { - console.error('APOS MODULE RESOLVE FAILED!', - 'FROM: ' + source, - 'TO: ' + path.join(sourceRoot, moduleName, 'apos', ...chunks) - ); - } - return resolved; - } - }; -} diff --git a/lib/vite-public-config.js b/lib/vite-public-config.js index eab3540..8e31484 100644 --- a/lib/vite-public-config.js +++ b/lib/vite-public-config.js @@ -1,9 +1,16 @@ module.exports = async ({ - input + sourceRoot, input }) => { + const apos = await import('./vite-plugin-apostrophe-alias.mjs'); /** @type {import('vite').UserConfig} */ return { + plugins: [ + apos.default({ + id: 'src', + sourceRoot + }) + ], build: { rollupOptions: { input