0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-03-03 22:57:08 -05:00
astro/packages/astro/snowpack-plugin.cjs
Matthew Phillips 016833a3bc
Honor user's hmr settings (#436)
* Honor user's hmr settings

This contains 2 fixes:

* If the user sets the hmrPort in their own snowpack config we use that port.
* If the user sets `window.HMR_WEBSOCKET_URL` we defer to that

* Adds the changeset
2021-06-14 16:10:29 -04:00

72 lines
3.2 KiB
JavaScript

const { readFile } = require('fs').promises;
// Snowpack plugins must be CommonJS :(
const transformPromise = import('./dist/compiler/index.js');
const DEFAULT_HMR_PORT = 12321;
/** @type {import('snowpack').SnowpackPluginFactory<any>} */
module.exports = (snowpackConfig, { resolvePackageUrl, renderers, astroConfig } = {}) => {
let hmrPort = DEFAULT_HMR_PORT;
return {
name: 'snowpack-astro',
knownEntrypoints: ['astro/dist/internal/h.js', 'astro/components/Prism.astro'],
resolve: {
input: ['.astro', '.md'],
output: ['.js', '.css'],
},
/**
* This injects our renderer plugins to the Astro runtime (as a bit of a hack).
*
* In a world where Snowpack supports virtual files, this won't be necessary and
* should be refactored to a virtual file that is imported by the runtime.
*
* Take a look at `/src/frontend/__astro_component.ts`. It relies on both
* `__rendererSources` and `__renderers` being defined, so we're creating those here.
*
* The output of this is the following (or something very close to it):
*
* ```js
* import * as __renderer_0 from '/_snowpack/link/packages/renderers/vue/index.js';
* import * as __renderer_1 from '/_snowpack/link/packages/renderers/svelte/index.js';
* import * as __renderer_2 from '/_snowpack/link/packages/renderers/preact/index.js';
* import * as __renderer_3 from '/_snowpack/link/packages/renderers/react/index.js';
* let __rendererSources = ["/_snowpack/link/packages/renderers/vue/client.js", "/_snowpack/link/packages/renderers/svelte/client.js", "/_snowpack/link/packages/renderers/preact/client.js", "/_snowpack/link/packages/renderers/react/client.js"];
* let __renderers = [__renderer_0, __renderer_1, __renderer_2, __renderer_3];
* // the original file contents
* ```
*/
async transform({contents, id, fileExt}) {
if (fileExt === '.js' && /__astro_component\.js/g.test(id)) {
const rendererServerPackages = renderers.map(({ server }) => server);
const rendererClientPackages = await Promise.all(renderers.map(({ client }) => resolvePackageUrl(client)));
const result = `${rendererServerPackages.map((pkg, i) => `import __renderer_${i} from "${pkg}";`).join('\n')}
let __rendererSources = [${rendererClientPackages.map(pkg => `"${pkg}"`).join(', ')}];
let __renderers = [${rendererServerPackages.map((_, i) => `__renderer_${i}`).join(', ')}];
${contents}`;
return result;
}
},
config(snowpackConfig) {
if(!isNaN(snowpackConfig.devOptions.hmrPort)) {
hmrPort = snowpackConfig.devOptions.hmrPort;
}
},
async load({ filePath }) {
const { compileComponent } = await transformPromise;
const projectRoot = snowpackConfig.root;
const contents = await readFile(filePath, 'utf-8');
const compileOptions = {
astroConfig,
hmrPort,
resolvePackageUrl,
renderers,
};
const result = await compileComponent(contents, { compileOptions, filename: filePath, projectRoot });
const output = {
'.js': { code: result.contents },
};
if (result.css) output['.css'] = result.css;
return output;
},
};
};