seia.js
Version:
Lightweight SSR framework for React Server Components
165 lines (164 loc) • 5.51 kB
JavaScript
import { relative } from 'node:path';
import { generate } from 'astring';
import sum from 'hash-sum';
import { name } from '../package.js';
import { changeExtension } from '../utils-path.js';
import { isObject } from '../utils.js';
export const injectClient = ({ clientBoundaries, config })=>{
return {
name: 'seia:inject-client',
resolveId (source) {
if (source.endsWith('\0client.js')) return {
id: '\0client.js',
moduleSideEffects: true
};
},
load (id) {
if (id === '\0client.js') {
const rawAst = injectManifest(clientBoundaries.map((path)=>[
'_' + sum(path),
path
]), config);
const ast = injectSpan(rawAst);
// TODO: well... sourcemap issue again.
const code = generate(ast);
return {
code
};
}
}
};
};
const dummySpan = {
start: 0,
end: 0
};
const s = (v)=>({
...v,
...dummySpan
});
const injectSpan = (node)=>{
if (Array.isArray(node)) return node.map(injectSpan);
if (isObject(node)) {
for(const key in node){
if (!Object.hasOwn(node, key)) continue;
const value = node[key];
node[key] = injectSpan(value);
}
return s(node);
}
return node;
};
const injectManifest = (manifestArray, { paths: { src } })=>({
type: 'Program',
sourceType: 'module',
body: [
{
type: 'ImportDeclaration',
specifiers: [
{
type: 'ImportSpecifier',
local: {
type: 'Identifier',
name: 'initClientModuleMap'
},
imported: {
type: 'Identifier',
name: 'initClientModuleMap'
}
},
{
type: 'ImportSpecifier',
local: {
type: 'Identifier',
name: 'run'
},
imported: {
type: 'Identifier',
name: 'run'
}
}
],
source: {
type: 'Literal',
value: `${name}/client`
}
},
...manifestArray.map(([id, path])=>({
type: 'ImportDeclaration',
specifiers: [
{
type: 'ImportNamespaceSpecifier',
local: {
type: 'Identifier',
name: id
}
}
],
source: {
type: 'Literal',
value: path
}
})),
{
type: 'VariableDeclaration',
declarations: [
{
type: 'VariableDeclarator',
id: {
type: 'Identifier',
name: 'clientModuleMap'
},
init: {
type: 'ObjectExpression',
properties: manifestArray.map(([id, path])=>({
type: 'Property',
key: {
type: 'Literal',
value: './' + changeExtension(relative(src, path), '.js')
},
value: {
type: 'Identifier',
name: id
},
kind: 'init',
method: false,
shorthand: false,
computed: false
}))
}
}
],
kind: 'const'
},
{
type: 'ExpressionStatement',
expression: {
type: 'CallExpression',
callee: {
type: 'Identifier',
name: 'initClientModuleMap'
},
arguments: [
{
type: 'Identifier',
name: 'clientModuleMap'
}
],
optional: false
}
},
{
type: 'ExpressionStatement',
expression: {
type: 'CallExpression',
callee: {
type: 'Identifier',
name: 'run'
},
arguments: [],
optional: false
}
}
]
});