flecks/packages/server/build/runtime.js

126 lines
4.2 KiB
JavaScript
Raw Normal View History

2024-02-03 20:31:35 -06:00
const {externals} = require('@flecks/build/src/server');
2022-02-25 04:58:08 -06:00
2024-01-25 06:42:31 -06:00
const D = require('@flecks/core/build/debug');
const debug = D('@flecks/server/build/runtime');
2024-02-05 17:08:26 -06:00
const {version} = require('../package.json');
2023-11-30 21:41:42 -06:00
module.exports = async (config, env, argv, flecks) => {
2024-01-22 09:16:07 -06:00
const runtimePath = await flecks.resolver.resolve('@flecks/server/runtime');
2023-11-30 21:41:42 -06:00
// Inject flecks configuration.
2024-01-16 00:28:20 -06:00
const paths = Object.keys(flecks.flecks);
const resolvedPaths = (await Promise.all(
paths.map(async (path) => [path, await flecks.resolver.resolve(path)]),
))
.filter(([, resolved]) => resolved)
.map(([path]) => path);
2024-01-22 09:16:07 -06:00
const runtime = {
config: JSON.stringify(flecks.config),
loadFlecks: [
'async () => (',
' Object.fromEntries(',
' (await Promise.all(',
' [',
...resolvedPaths.map((path) => [
' (async () => {',
' try {',
` return ['${path}', await import('${path}')];`,
' }',
' catch (error) {',
' if (!error.message.startsWith("Cannot find module")) {',
' throw error;',
' }',
' }',
' })(),',
]).flat(),
' ],',
' ))',
' .filter((entry) => entry),',
' )',
')',
].join('\n'),
2024-02-05 17:08:26 -06:00
version: JSON.stringify(version),
2024-01-22 09:16:07 -06:00
...await flecks.invokeAsync('@flecks/server.runtime'),
};
const runtimeString = `{${
Object.entries(runtime)
.map(([key, value]) => `"${key}": ${value}`).join(', ')
}}`;
2023-11-30 21:41:42 -06:00
const source = [
"process.env.FLECKS_CORE_BUILD_TARGET = 'server';",
2024-01-22 09:16:07 -06:00
`module.exports = (async () => (${runtimeString}))();`,
2023-11-30 21:41:42 -06:00
];
// HMR.
source.push('if (module.hot) {');
// Keep HMR junk out of our output path.
2024-01-27 04:01:31 -06:00
source.push(' const {glob} = require("glob");');
2023-11-30 21:41:42 -06:00
source.push(' const {join} = require("path");');
2024-01-27 04:01:31 -06:00
source.push(' const {unlink} = require("fs/promises");');
2023-11-30 21:41:42 -06:00
source.push(' let previousHash = __webpack_hash__;');
2024-01-27 04:01:31 -06:00
source.push(' module.hot.addStatusHandler(async (status) => {');
2023-11-30 21:41:42 -06:00
source.push(' if ("idle" === status) {');
2024-01-27 04:01:31 -06:00
source.push(' const disposing = await glob(');
2023-11-30 21:41:42 -06:00
source.push(` join('${config.output.path}', \`*\${previousHash}.hot-update.*\`),`);
source.push(' );');
2024-01-27 04:01:31 -06:00
source.push(' await Promise.all(disposing.map((filename) => unlink(filename)));');
2023-11-30 21:41:42 -06:00
source.push(' previousHash = __webpack_hash__;');
source.push(' }');
source.push(' });');
// Hooks for each fleck.
2024-01-16 00:28:20 -06:00
resolvedPaths.forEach((path) => {
2023-11-30 21:41:42 -06:00
source.push(` module.hot.accept('${path}', async () => {`);
2024-02-06 08:16:53 -06:00
source.push(` const M = require('${path}')`);
source.push(' try {');
source.push(` global.flecks.invokeSequential('@flecks/core.hmr', '${path}', M);`);
source.push(` global.flecks.refresh('${path}', M);`);
source.push(' }');
source.push(' catch (error) {');
// eslint-disable-next-line no-template-curly-in-string
source.push(' console.error(`HMR failed for fleck: ${error.message}`);');
source.push(' module.hot.invalidate();');
source.push(' }');
2022-02-25 04:58:08 -06:00
source.push(' });');
2023-11-30 21:41:42 -06:00
});
source.push('}');
// Create runtime.
config.module.rules.push(
{
2024-01-22 09:16:07 -06:00
test: runtimePath,
2023-11-30 21:41:42 -06:00
use: [
{
2024-01-22 09:16:07 -06:00
loader: runtimePath,
2023-11-30 21:41:42 -06:00
options: {
source: source.join('\n'),
},
},
],
},
);
const allowlist = [
'@flecks/server/entry',
'@flecks/server/runtime',
/^@babel\/runtime\/helpers\/esm/,
];
2024-01-22 09:16:07 -06:00
config.resolve.alias['@flecks/server/runtime$'] = runtimePath;
2024-01-25 06:42:31 -06:00
Object.entries(flecks.resolver.aliases).forEach(([path, request]) => {
debug('server runtime de-externalized %s, alias: %s', path, request);
allowlist.push(new RegExp(`^${path}`));
});
// Stubs.
flecks.stubs.forEach((stub) => {
config.resolve.alias[stub] = false;
});
2024-02-05 17:08:26 -06:00
await flecks.runtimeCompiler('server', config, env, argv);
2023-11-30 21:41:42 -06:00
// Rewrite to signals for HMR.
if ('production' !== argv.mode) {
2024-01-22 09:16:07 -06:00
allowlist.push(/^webpack\/hot\/signal/);
2023-11-30 21:41:42 -06:00
}
// Externalize the rest.
2024-02-03 20:31:35 -06:00
config.externals = await externals({
additionalModuleDirs: flecks.resolver.modules,
allowlist,
importType: 'commonjs',
});
2022-02-25 04:58:08 -06:00
};