@wrdagency/react-islands 2.0.11 → 2.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.js +1 -1
- package/dist/index.d.ts +5 -7
- package/package.json +1 -1
- package/src/bin/commands/build.ts +19 -50
- package/src/bin/commands/watch.ts +41 -0
- package/src/bin/index.ts +2 -0
- package/src/bin/rollup/common.ts +48 -0
- package/src/bin/rollup/index.ts +3 -182
- package/src/bin/rollup/island.ts +141 -0
- package/src/bin/rollup/plugins/runScriptAfterBuildPlugin.ts +3 -2
- package/src/bin/rollup/plugins/virtualizeDependencyPlugin.ts +9 -6
- package/src/bin/rollup/run.ts +65 -0
- package/src/bin/util/code-gen.ts +66 -0
- package/src/bin/util/config.ts +68 -0
- package/src/bin/util/output.ts +67 -0
- package/src/index.tsx +1 -1
- package/src/bin/rollup/console.ts +0 -23
- package/src/bin/rollup/generation.ts +0 -57
- package/src/bin/rollup/options.ts +0 -74
package/bin/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import e
|
|
2
|
+
import e from"@rollup/plugin-commonjs";import n from"@rollup/plugin-node-resolve";import t from"@rollup/plugin-replace";import o from"@rollup/plugin-terser";import r from"path";import{rollup as s,watch as i}from"rollup";import a from"@rollup/plugin-typescript";import{typescriptPaths as c}from"rollup-plugin-typescript-paths";import l,{readFileSync as u}from"fs";import{exec as p}from"child_process";import{promisify as m}from"util";import d from"yocto-spinner";import f from"command-line-args";import g from"command-line-usage";class h{lines=[];import(e,n){return n||(n=h.packageNameToProperty(e)),this.add(`import * as ${n} from "${e}"`)}createGlobalObject(e){return this.add(e.split(".").map(e=>e.trim()).filter(Boolean).map((e,n,t)=>{const o="window."+t.slice(0,n+1).join(".");return`${o} = ${o} || {}`}))}setGlobalObjectProperty(e,n,t){return this.add(`window.${e}['${n}'] = ${t}`)}static packageNameToProperty(e){return e.replace(/^@/,"").replace(/\//g,"_").replace(/[-_](.)/g,(e,n)=>n.toUpperCase()).replace(/^[a-z]/,e=>e.toUpperCase())}static renderReactComponentToFile(e,n){return`var server = require('react-dom/server');\nvar fs = require('node:fs/promises');\nvar path = require('node:path');\nconst html = server.renderToString( ${n}( {} ) );\nconst file = path.resolve(__dirname, '${e}');\nfs.writeFile(file, html, { flag: "w+" });`}add(e){return Array.isArray(e)?this.lines.push(...e):this.lines.push(e),this}out(){return this.lines.join(";\n")}}function y(e){const{dependencies:n,namespace:t=""}=e,o="\0virtual-entry";return{name:"rollup-plugin-virtualize-dependency",resolveId:e=>"virtual-entry"===e?o:null,load(e){if(e!==o)return null;const r=new h;r.createGlobalObject(t);for(const e of n){const n=h.packageNameToProperty(e);r.import(e,n),r.setGlobalObjectProperty(t,n,n)}return r.out()}}}async function w(e){const{output:n,...t}=e;let o,r=!1;try{o=await s(t),await o.write(n)}catch(e){r=!0,console.error(e)}return o&&await o.close(),!r}function j(e){const{output:n,...t}=e,o=i({...t,output:n,watch:{clearScreen:!1}});return o.on("event",e=>{"BUNDLE_END"===e.code&&e.result&&e.result.close()}),o}function b(s){const{output:i,minify:a,jsx:c,common:l}=s;return{input:"virtual-entry",jsx:c,output:{name:"Islands._Common",file:r.resolve(i,"common.js"),format:"iife"},plugins:[t({preventAssignment:!0,"process.env.NODE_ENV":JSON.stringify("production")}),y({dependencies:l,namespace:"Islands._Common"}),n(),e(),a&&o()]}}const v=m(p);class ${line(e){console.log(e)}async spinner(e,n){const t=d({text:`${e}...`}).start();await n()?t.success(`Succeeded: ${e}`):t.warning(`Failed: ${e}`)}watcher(e,n){const t=d({text:`Rebuilding ${e}...`});let o=0;n.on("event",n=>{if("START"===n.code)t.clear(),t.start(),o=Date.now();else if("END"===n.code){const n=Date.now()-o;t.success(`Rebuilt: ${e} in ${n}ms.`)}else"ERROR"===n.code&&(t.warning(`Failed: ${e}`),console.error(n.error))})}async command(e){try{const{stdout:n,stderr:t}=await v(e);return n&&console.log(n),t&&console.error(t),n}catch(e){throw console.error(e),e}}}function x(e){const{deleteAfterRunning:n=!1}=e;return{name:"rollup-plugin-run-script-after-builder",writeBundle(e,t){const o=e.dir?e.dir:r.dirname(e.file||"");for(const[e,s]of Object.entries(t)){const t=r.resolve(o,e);if("chunk"!==s.type||!s.isEntry)return;if(!t&&!t.endsWith("js"))return;if(!l.existsSync(t))return;(new $).command(`node ${t}`).then(()=>{n&&l.unlinkSync(t)})}}}}function N(r,s){const{name:i,input:l,output:u,minify:p,ssg:m,jsx:d,typescript:f,common:g}=r,{name:h=`Islands.${i}`,subName:y,format:w,globals:j={},prefix:b,suffix:v,plugins:$=[]}=s;return{input:l,external:Object.keys(j),jsx:d,output:{name:h,globals:j,format:w,entryFileNames:`[name]/${y}`,dir:u,banner:b&&(e=>b(e.name)),footer:v&&(e=>v(e.name))},plugins:[n({extensions:[".cjs",".mjs",".js",".json",".node",".jsx",".ts",".tsx"]}),e(),t({preventAssignment:!0,"process.env.NODE_ENV":JSON.stringify("production")}),p&&o(),f&&a({outputToFilesystem:!0,noForceEmit:!0,compilerOptions:{outDir:u,jsx:d}}),f&&c(),...$]}}function O(e){return N(e,{subName:"client.js",format:"iife",globals:e.common.reduce((e,n)=>({...e,[n]:`Islands._Common["${h.packageNameToProperty(n)}"]`}),{}),suffix:e=>`\nwindow.Islands['${e}']?.render('${e}')`})}function k(e){const n=[O(e)];return e.ssg&&n.push(function(e){return N(e,{subName:"server.cjs",format:"cjs",suffix:()=>h.renderReactComponentToFile("ssg.html","module.exports.component"),plugins:[x({deleteAfterRunning:!0})]})}(e)),n}function S(e){return async function(e){let n=!0;for(const t of e)await w(t)||(n=!1);return n}(k(e))}function C(e){return j(O(e))}class T{args;callback;description;constructor(e){let{args:n,callback:t,description:o}=e;n.push({name:"help",alias:"h",type:Boolean,description:"Display this usage guide."}),this.args=n,this.callback=t,this.description=o}run(e){const{help:n,...t}=f(this.args,{argv:e});if(!n)return this.callback(t);console.log(g([{header:"Options",optionList:this.args}]))}}function _(e){const n=u(e,"utf8");return function(e){const n=(e,n)=>!1!==e&&(!0===e||n);return{islands:e.islands,output:e.output||"./dist/",minify:n(e.minify,!0),ssg:n(e.ssg,!0),jsx:e.jsx||"react-jsx",typescript:n(e.ssg,!1),common:e.common||["react","react/jsx-runtime","react-dom/client","@wrdagency/react-islands"]}}(JSON.parse(n))}!async function(e){const{command:n,help:t=!1,_unknown:o=[]}=f([{name:"command",type:String,defaultOption:!0},{name:"help",alias:"h",type:Boolean,description:"Display this usage guide."}],{stopAtFirstUnknown:!0});if(n&&n in e)return e[n].run([...o,t&&"--help"].filter(Boolean));if(t){const n=Object.keys(e).map(n=>({name:n,summary:e[n].description})),t=g([{header:"Synopsis",content:"npx react-islands <command> <options>"},{header:"Command List",content:n}]);console.log(t)}else console.error(`Command '${n}' not recognized by React Islands.`)}({build:new T({description:"Build and statically render the islands.",args:[{name:"config",type:String,alias:"c",description:"The config file to use.",defaultValue:"islands.config.json"}],callback:async e=>{const{config:n}=e,t=new $,o=_(n);o.common&&await t.spinner("Creating common dependencies file",async()=>w(b(o)));for(const[e,n]of Object.entries(o.islands))await t.spinner(`Creating island ${e}`,()=>S({name:e,input:n,...o}))}}),watch:new T({description:"Watch & build the islands for development",args:[{name:"config",type:String,alias:"c",description:"The config file to use.",defaultValue:"islands.config.json"}],callback:async e=>{const{config:n}=e,t=new $,o=_(n);if(o.common){const e=j(b(o));t.watcher("Common Dependencies",e)}for(const[e,n]of Object.entries(o.islands)){const r=C({name:e,input:n,...o});t.watcher(e,r)}}})});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { FC } from 'react';
|
|
2
|
-
import { JsxPreset } from 'rollup';
|
|
3
2
|
|
|
4
3
|
interface IslandRenderOptions {
|
|
5
4
|
shouldHydrate: boolean;
|
|
@@ -34,16 +33,15 @@ declare function withProps<T>(component: FC<T>, setProps: Partial<T>): FC<T>;
|
|
|
34
33
|
*/
|
|
35
34
|
declare function isServer(): boolean;
|
|
36
35
|
|
|
37
|
-
type
|
|
38
|
-
|
|
39
|
-
input: string;
|
|
36
|
+
type ConfigOptions = {
|
|
37
|
+
islands: Record<string, string>;
|
|
40
38
|
output: string;
|
|
41
39
|
minify?: boolean;
|
|
42
40
|
ssg?: boolean;
|
|
43
|
-
jsx?:
|
|
41
|
+
jsx?: "react" | "react-jsx" | "preserve" | "preserve-react";
|
|
44
42
|
typescript?: boolean;
|
|
45
|
-
common?: string[]
|
|
43
|
+
common?: string[];
|
|
46
44
|
};
|
|
47
45
|
|
|
48
46
|
export { Island, isServer, withProps };
|
|
49
|
-
export type {
|
|
47
|
+
export type { ConfigOptions };
|
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { OutputOptions } from "rollup";
|
|
3
|
-
import yoctoSpinner from "yocto-spinner";
|
|
4
|
-
import { createCommonConfig, createRollupConfigs, runRollup } from "../rollup";
|
|
1
|
+
import { buildCommon, buildIsland } from "../rollup";
|
|
5
2
|
import { Command } from "../util/command";
|
|
3
|
+
import { readConfig } from "../util/config";
|
|
4
|
+
import { Output } from "../util/output";
|
|
6
5
|
|
|
7
6
|
export default new Command({
|
|
8
7
|
description: "Build and statically render the islands.",
|
|
@@ -17,57 +16,27 @@ export default new Command({
|
|
|
17
16
|
},
|
|
18
17
|
],
|
|
19
18
|
callback: async (args) => {
|
|
20
|
-
const { config } = args;
|
|
19
|
+
const { config: configPath } = args;
|
|
21
20
|
|
|
22
|
-
const
|
|
21
|
+
const output = new Output();
|
|
22
|
+
const config = readConfig(configPath);
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}).start();
|
|
30
|
-
|
|
31
|
-
const commonRollupConfig = createCommonConfig(restConfig);
|
|
32
|
-
const { output, ...input } = commonRollupConfig;
|
|
33
|
-
const success = await runRollup(input, output as OutputOptions);
|
|
34
|
-
|
|
35
|
-
if (success) {
|
|
36
|
-
spinner.success(`Succeeded: common dependencies file`);
|
|
37
|
-
} else {
|
|
38
|
-
spinner.warning(`Failed: common dependencies file`);
|
|
39
|
-
}
|
|
24
|
+
// 1. Build common dependencies.
|
|
25
|
+
if (config.common) {
|
|
26
|
+
await output.spinner("Creating common dependencies file", async () => {
|
|
27
|
+
return buildCommon(config);
|
|
28
|
+
});
|
|
40
29
|
}
|
|
41
30
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
...restConfig,
|
|
31
|
+
// 2. Setup watcher for each island.
|
|
32
|
+
for (const [name, input] of Object.entries(config.islands)) {
|
|
33
|
+
await output.spinner(`Creating island ${name}`, () => {
|
|
34
|
+
return buildIsland({
|
|
35
|
+
name,
|
|
36
|
+
input,
|
|
37
|
+
...config,
|
|
38
|
+
});
|
|
51
39
|
});
|
|
52
|
-
|
|
53
|
-
let hadFailure = false;
|
|
54
|
-
|
|
55
|
-
for (const rollupConfig of rollupConfigs) {
|
|
56
|
-
const { output, ...input } = rollupConfig;
|
|
57
|
-
const success = await runRollup(input, output as OutputOptions);
|
|
58
|
-
|
|
59
|
-
if (!success) {
|
|
60
|
-
hadFailure = true;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
rollupConfigs.map(async (options) => {});
|
|
65
|
-
|
|
66
|
-
if (hadFailure) {
|
|
67
|
-
spinner.warning(`Failed island: ${name}`);
|
|
68
|
-
} else {
|
|
69
|
-
spinner.success(`Succeeded island: ${name}`);
|
|
70
|
-
}
|
|
71
40
|
}
|
|
72
41
|
},
|
|
73
42
|
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { watchCommon, watchIsland } from "../rollup";
|
|
2
|
+
import { Command } from "../util/command";
|
|
3
|
+
import { readConfig } from "../util/config";
|
|
4
|
+
import { Output } from "../util/output";
|
|
5
|
+
|
|
6
|
+
export default new Command({
|
|
7
|
+
description: "Watch & build the islands for development",
|
|
8
|
+
args: [
|
|
9
|
+
{
|
|
10
|
+
name: "config",
|
|
11
|
+
type: String,
|
|
12
|
+
alias: "c",
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
description: "The config file to use.",
|
|
15
|
+
defaultValue: "islands.config.json",
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
callback: async (args) => {
|
|
19
|
+
const { config: configPath } = args;
|
|
20
|
+
|
|
21
|
+
const output = new Output();
|
|
22
|
+
const config = readConfig(configPath);
|
|
23
|
+
|
|
24
|
+
// 1. Build common dependencies.
|
|
25
|
+
if (config.common) {
|
|
26
|
+
const watcher = watchCommon(config);
|
|
27
|
+
output.watcher("Common Dependencies", watcher);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 2. Setup watcher for each island.
|
|
31
|
+
for (const [name, input] of Object.entries(config.islands)) {
|
|
32
|
+
const watcher = watchIsland({
|
|
33
|
+
name,
|
|
34
|
+
input,
|
|
35
|
+
...config,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
output.watcher(name, watcher);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
});
|
package/src/bin/index.ts
CHANGED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import commonjsPlugin from "@rollup/plugin-commonjs";
|
|
2
|
+
import resolvePlugin from "@rollup/plugin-node-resolve";
|
|
3
|
+
import replacePlugin from "@rollup/plugin-replace";
|
|
4
|
+
import terserPlugin from "@rollup/plugin-terser";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import { RollupOptions } from "rollup";
|
|
7
|
+
import { NormalizedConfigOptions } from "../util/config";
|
|
8
|
+
import { virtualizeDependencyPlugin } from "./plugins/virtualizeDependencyPlugin";
|
|
9
|
+
import { runRollup, watchRollup } from "./run";
|
|
10
|
+
|
|
11
|
+
export function createCommonConfig(
|
|
12
|
+
options: NormalizedConfigOptions
|
|
13
|
+
): RollupOptions {
|
|
14
|
+
const { output, minify, jsx, common } = options;
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
input: "virtual-entry",
|
|
18
|
+
jsx,
|
|
19
|
+
output: {
|
|
20
|
+
name: "Islands._Common",
|
|
21
|
+
file: path.resolve(output, "common.js"),
|
|
22
|
+
format: "iife",
|
|
23
|
+
},
|
|
24
|
+
plugins: [
|
|
25
|
+
replacePlugin({
|
|
26
|
+
preventAssignment: true,
|
|
27
|
+
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
28
|
+
}),
|
|
29
|
+
virtualizeDependencyPlugin({
|
|
30
|
+
dependencies: common,
|
|
31
|
+
namespace: "Islands._Common",
|
|
32
|
+
}),
|
|
33
|
+
resolvePlugin(),
|
|
34
|
+
commonjsPlugin(),
|
|
35
|
+
minify && terserPlugin(),
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function buildCommon(
|
|
41
|
+
options: NormalizedConfigOptions
|
|
42
|
+
): Promise<boolean> {
|
|
43
|
+
return runRollup(createCommonConfig(options));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function watchCommon(options: NormalizedConfigOptions) {
|
|
47
|
+
return watchRollup(createCommonConfig(options));
|
|
48
|
+
}
|
package/src/bin/rollup/index.ts
CHANGED
|
@@ -1,182 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import terserPlugin from "@rollup/plugin-terser";
|
|
5
|
-
import typescriptPlugin from "@rollup/plugin-typescript";
|
|
6
|
-
import path from "path";
|
|
7
|
-
import {
|
|
8
|
-
InputOptions,
|
|
9
|
-
ModuleFormat,
|
|
10
|
-
OutputOptions,
|
|
11
|
-
Plugin,
|
|
12
|
-
rollup,
|
|
13
|
-
RollupBuild,
|
|
14
|
-
RollupOptions,
|
|
15
|
-
} from "rollup";
|
|
16
|
-
import { typescriptPaths as typescriptPathsPlugin } from "rollup-plugin-typescript-paths";
|
|
17
|
-
import * as codeGen from "./generation";
|
|
18
|
-
import { BuildOptions, normalizeOptions } from "./options";
|
|
19
|
-
import { runScriptAfterBuildPlugin } from "./plugins/runScriptAfterBuildPlugin";
|
|
20
|
-
import { virtualizeDependencyPlugin } from "./plugins/virtualizeDependencyPlugin";
|
|
21
|
-
|
|
22
|
-
export function createRollupConfigs(options: BuildOptions): RollupOptions[] {
|
|
23
|
-
const normalized = normalizeOptions(options);
|
|
24
|
-
const { name, input, output, minify, ssg, jsx, typescript, common } =
|
|
25
|
-
normalized;
|
|
26
|
-
|
|
27
|
-
const configs: (RollupOptions | null)[] = [];
|
|
28
|
-
|
|
29
|
-
const createRollupConfig = (opts: {
|
|
30
|
-
active?: boolean;
|
|
31
|
-
name?: string;
|
|
32
|
-
subName: string;
|
|
33
|
-
format: ModuleFormat;
|
|
34
|
-
globals?: Record<string, string>;
|
|
35
|
-
prefix?: (name: string) => string;
|
|
36
|
-
suffix?: (name: string) => string;
|
|
37
|
-
plugins?: Plugin[];
|
|
38
|
-
}): RollupOptions | null => {
|
|
39
|
-
const {
|
|
40
|
-
active = true,
|
|
41
|
-
name: mainName = `Islands.${name}`,
|
|
42
|
-
subName,
|
|
43
|
-
format,
|
|
44
|
-
globals = {},
|
|
45
|
-
prefix,
|
|
46
|
-
suffix,
|
|
47
|
-
plugins = [],
|
|
48
|
-
} = opts;
|
|
49
|
-
|
|
50
|
-
if (!active) {
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
input,
|
|
56
|
-
external: Object.keys(globals),
|
|
57
|
-
jsx,
|
|
58
|
-
output: {
|
|
59
|
-
name: mainName,
|
|
60
|
-
globals,
|
|
61
|
-
format,
|
|
62
|
-
entryFileNames: `[name]/${subName}`,
|
|
63
|
-
dir: output,
|
|
64
|
-
banner: prefix && ((chunk) => prefix(chunk.name)),
|
|
65
|
-
footer: suffix && ((chunk) => suffix(chunk.name)),
|
|
66
|
-
},
|
|
67
|
-
plugins: [
|
|
68
|
-
resolvePlugin({
|
|
69
|
-
extensions: [
|
|
70
|
-
".cjs",
|
|
71
|
-
".mjs",
|
|
72
|
-
".js",
|
|
73
|
-
".json",
|
|
74
|
-
".node",
|
|
75
|
-
".jsx",
|
|
76
|
-
".ts",
|
|
77
|
-
".tsx",
|
|
78
|
-
],
|
|
79
|
-
}),
|
|
80
|
-
commonjsPlugin(),
|
|
81
|
-
replacePlugin({
|
|
82
|
-
preventAssignment: true,
|
|
83
|
-
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
84
|
-
}),
|
|
85
|
-
minify && terserPlugin(),
|
|
86
|
-
typescript &&
|
|
87
|
-
typescriptPlugin({
|
|
88
|
-
noForceEmit: true,
|
|
89
|
-
compilerOptions: {
|
|
90
|
-
outDir: output,
|
|
91
|
-
jsx,
|
|
92
|
-
},
|
|
93
|
-
}),
|
|
94
|
-
typescript && typescriptPathsPlugin(),
|
|
95
|
-
...plugins,
|
|
96
|
-
],
|
|
97
|
-
};
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
configs.push(
|
|
101
|
-
createRollupConfig({
|
|
102
|
-
active: true,
|
|
103
|
-
subName: "client.js",
|
|
104
|
-
format: "iife",
|
|
105
|
-
globals: common,
|
|
106
|
-
suffix: (name) => `\nwindow.Islands['${name}']?.render('${name}')`,
|
|
107
|
-
})
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
configs.push(
|
|
111
|
-
createRollupConfig({
|
|
112
|
-
active: ssg,
|
|
113
|
-
subName: "server.cjs",
|
|
114
|
-
format: "cjs",
|
|
115
|
-
suffix: () =>
|
|
116
|
-
codeGen.renderComponentToFile("ssg.html", "module.exports.component"),
|
|
117
|
-
plugins: [
|
|
118
|
-
runScriptAfterBuildPlugin({
|
|
119
|
-
deleteAfterRunning: true,
|
|
120
|
-
}),
|
|
121
|
-
],
|
|
122
|
-
})
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
return configs.filter(isRollupOptions);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function createCommonConfig(options: BuildOptions): RollupOptions {
|
|
129
|
-
const normalized = normalizeOptions(options);
|
|
130
|
-
const { output, minify, jsx, common } = normalized;
|
|
131
|
-
|
|
132
|
-
return {
|
|
133
|
-
input: "virtual-entry",
|
|
134
|
-
jsx,
|
|
135
|
-
output: {
|
|
136
|
-
name: "Islands._Common",
|
|
137
|
-
file: path.resolve(output, "common.js"),
|
|
138
|
-
format: "iife",
|
|
139
|
-
},
|
|
140
|
-
plugins: [
|
|
141
|
-
replacePlugin({
|
|
142
|
-
preventAssignment: true,
|
|
143
|
-
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
144
|
-
}),
|
|
145
|
-
virtualizeDependencyPlugin({
|
|
146
|
-
dependencies: common,
|
|
147
|
-
namespace: "Islands._Common",
|
|
148
|
-
}),
|
|
149
|
-
resolvePlugin(),
|
|
150
|
-
commonjsPlugin(),
|
|
151
|
-
minify && terserPlugin(),
|
|
152
|
-
],
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function isRollupOptions(
|
|
157
|
-
config: RollupOptions | null
|
|
158
|
-
): config is RollupOptions {
|
|
159
|
-
return config !== null;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export async function runRollup(
|
|
163
|
-
inputOptions: InputOptions,
|
|
164
|
-
outputOptions: OutputOptions
|
|
165
|
-
) {
|
|
166
|
-
let bundle: RollupBuild | undefined;
|
|
167
|
-
let buildFailed = false;
|
|
168
|
-
|
|
169
|
-
try {
|
|
170
|
-
bundle = await rollup(inputOptions);
|
|
171
|
-
await bundle.write(outputOptions);
|
|
172
|
-
} catch (error) {
|
|
173
|
-
buildFailed = true;
|
|
174
|
-
console.error(error);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
if (bundle) {
|
|
178
|
-
await bundle.close();
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return !buildFailed;
|
|
182
|
-
}
|
|
1
|
+
export * from "./common";
|
|
2
|
+
export * from "./island";
|
|
3
|
+
export * from "./run";
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import commonjsPlugin from "@rollup/plugin-commonjs";
|
|
2
|
+
import resolvePlugin from "@rollup/plugin-node-resolve";
|
|
3
|
+
import replacePlugin from "@rollup/plugin-replace";
|
|
4
|
+
import terserPlugin from "@rollup/plugin-terser";
|
|
5
|
+
import typescriptPlugin from "@rollup/plugin-typescript";
|
|
6
|
+
import { ModuleFormat, Plugin, RollupOptions } from "rollup";
|
|
7
|
+
import { typescriptPaths as typescriptPathsPlugin } from "rollup-plugin-typescript-paths";
|
|
8
|
+
import { CodeGen } from "../util/code-gen";
|
|
9
|
+
import { IndividualIslandConfigOptions } from "../util/config";
|
|
10
|
+
import { runScriptAfterBuildPlugin } from "./plugins/runScriptAfterBuildPlugin";
|
|
11
|
+
import { runRollups, watchRollup } from "./run";
|
|
12
|
+
|
|
13
|
+
function createIslandRollupConfig(
|
|
14
|
+
config: IndividualIslandConfigOptions,
|
|
15
|
+
opts: {
|
|
16
|
+
name?: string;
|
|
17
|
+
subName: string;
|
|
18
|
+
format: ModuleFormat;
|
|
19
|
+
globals?: Record<string, string>;
|
|
20
|
+
prefix?: (name: string) => string;
|
|
21
|
+
suffix?: (name: string) => string;
|
|
22
|
+
plugins?: Plugin[];
|
|
23
|
+
}
|
|
24
|
+
): RollupOptions {
|
|
25
|
+
const { name, input, output, minify, ssg, jsx, typescript, common } = config;
|
|
26
|
+
|
|
27
|
+
const {
|
|
28
|
+
name: mainName = `Islands.${name}`,
|
|
29
|
+
subName,
|
|
30
|
+
format,
|
|
31
|
+
globals = {},
|
|
32
|
+
prefix,
|
|
33
|
+
suffix,
|
|
34
|
+
plugins = [],
|
|
35
|
+
} = opts;
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
input,
|
|
39
|
+
external: Object.keys(globals),
|
|
40
|
+
jsx,
|
|
41
|
+
output: {
|
|
42
|
+
name: mainName,
|
|
43
|
+
globals,
|
|
44
|
+
format,
|
|
45
|
+
entryFileNames: `[name]/${subName}`,
|
|
46
|
+
dir: output,
|
|
47
|
+
banner: prefix && ((chunk) => prefix(chunk.name)),
|
|
48
|
+
footer: suffix && ((chunk) => suffix(chunk.name)),
|
|
49
|
+
},
|
|
50
|
+
plugins: [
|
|
51
|
+
resolvePlugin({
|
|
52
|
+
extensions: [
|
|
53
|
+
".cjs",
|
|
54
|
+
".mjs",
|
|
55
|
+
".js",
|
|
56
|
+
".json",
|
|
57
|
+
".node",
|
|
58
|
+
".jsx",
|
|
59
|
+
".ts",
|
|
60
|
+
".tsx",
|
|
61
|
+
],
|
|
62
|
+
}),
|
|
63
|
+
commonjsPlugin(),
|
|
64
|
+
replacePlugin({
|
|
65
|
+
preventAssignment: true,
|
|
66
|
+
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
67
|
+
}),
|
|
68
|
+
minify && terserPlugin(),
|
|
69
|
+
typescript &&
|
|
70
|
+
typescriptPlugin({
|
|
71
|
+
outputToFilesystem: true,
|
|
72
|
+
noForceEmit: true,
|
|
73
|
+
compilerOptions: {
|
|
74
|
+
outDir: output,
|
|
75
|
+
jsx,
|
|
76
|
+
},
|
|
77
|
+
}),
|
|
78
|
+
typescript && typescriptPathsPlugin(),
|
|
79
|
+
...plugins,
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function createIslandRollupConfigClient(
|
|
85
|
+
config: IndividualIslandConfigOptions
|
|
86
|
+
): RollupOptions {
|
|
87
|
+
return createIslandRollupConfig(config, {
|
|
88
|
+
subName: "client.js",
|
|
89
|
+
format: "iife",
|
|
90
|
+
globals: config.common.reduce((globals, packageName) => {
|
|
91
|
+
return {
|
|
92
|
+
...globals,
|
|
93
|
+
[packageName]: `Islands._Common["${CodeGen.packageNameToProperty(
|
|
94
|
+
packageName
|
|
95
|
+
)}"]`,
|
|
96
|
+
};
|
|
97
|
+
}, {}),
|
|
98
|
+
suffix: (name) => `\nwindow.Islands['${name}']?.render('${name}')`,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function createIslandRollupConfigServer(
|
|
103
|
+
config: IndividualIslandConfigOptions
|
|
104
|
+
): RollupOptions {
|
|
105
|
+
return createIslandRollupConfig(config, {
|
|
106
|
+
subName: "server.cjs",
|
|
107
|
+
format: "cjs",
|
|
108
|
+
suffix: () =>
|
|
109
|
+
CodeGen.renderReactComponentToFile(
|
|
110
|
+
"ssg.html",
|
|
111
|
+
"module.exports.component"
|
|
112
|
+
),
|
|
113
|
+
plugins: [
|
|
114
|
+
runScriptAfterBuildPlugin({
|
|
115
|
+
deleteAfterRunning: true,
|
|
116
|
+
}),
|
|
117
|
+
],
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function createIslandRollupConfigs(
|
|
122
|
+
config: IndividualIslandConfigOptions
|
|
123
|
+
): RollupOptions[] {
|
|
124
|
+
const configs: RollupOptions[] = [createIslandRollupConfigClient(config)];
|
|
125
|
+
|
|
126
|
+
if (config.ssg) {
|
|
127
|
+
configs.push(createIslandRollupConfigServer(config));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return configs;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function buildIsland(
|
|
134
|
+
options: IndividualIslandConfigOptions
|
|
135
|
+
): Promise<boolean> {
|
|
136
|
+
return runRollups(createIslandRollupConfigs(options));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function watchIsland(options: IndividualIslandConfigOptions) {
|
|
140
|
+
return watchRollup(createIslandRollupConfigClient(options));
|
|
141
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { Plugin } from "rollup";
|
|
4
|
-
import {
|
|
4
|
+
import { Output } from "../../util/output";
|
|
5
5
|
|
|
6
6
|
type Options = {
|
|
7
7
|
deleteAfterRunning?: boolean;
|
|
@@ -32,7 +32,8 @@ export function runScriptAfterBuildPlugin(opts: Options): Plugin {
|
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
const out = new Output();
|
|
36
|
+
out.command(`node ${filePath}`).then(() => {
|
|
36
37
|
if (deleteAfterRunning) {
|
|
37
38
|
fs.unlinkSync(filePath);
|
|
38
39
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Plugin } from "rollup";
|
|
2
|
-
import
|
|
2
|
+
import { CodeGen } from "../../util/code-gen";
|
|
3
3
|
|
|
4
4
|
type Options = {
|
|
5
|
-
dependencies:
|
|
5
|
+
dependencies: string[];
|
|
6
6
|
namespace?: string;
|
|
7
7
|
};
|
|
8
8
|
|
|
@@ -22,13 +22,16 @@ export function virtualizeDependencyPlugin(opts: Options): Plugin {
|
|
|
22
22
|
return null;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
const code = new CodeGen();
|
|
26
|
+
code.createGlobalObject(namespace);
|
|
26
27
|
|
|
27
|
-
for (const
|
|
28
|
-
|
|
28
|
+
for (const packageName of dependencies) {
|
|
29
|
+
const name = CodeGen.packageNameToProperty(packageName);
|
|
30
|
+
code.import(packageName, name);
|
|
31
|
+
code.setGlobalObjectProperty(namespace, name, name);
|
|
29
32
|
}
|
|
30
33
|
|
|
31
|
-
return
|
|
34
|
+
return code.out();
|
|
32
35
|
},
|
|
33
36
|
};
|
|
34
37
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OutputOptions,
|
|
3
|
+
rollup,
|
|
4
|
+
RollupBuild,
|
|
5
|
+
RollupOptions,
|
|
6
|
+
RollupWatcher,
|
|
7
|
+
watch,
|
|
8
|
+
} from "rollup";
|
|
9
|
+
|
|
10
|
+
export async function runRollup(options: RollupOptions): Promise<boolean> {
|
|
11
|
+
const { output, ...input } = options;
|
|
12
|
+
|
|
13
|
+
let bundle: RollupBuild | undefined;
|
|
14
|
+
let buildFailed = false;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
bundle = await rollup(input);
|
|
18
|
+
await bundle.write(output as OutputOptions);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
buildFailed = true;
|
|
21
|
+
console.error(error);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (bundle) {
|
|
25
|
+
await bundle.close();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return !buildFailed;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function runRollups(options: RollupOptions[]): Promise<boolean> {
|
|
32
|
+
let isSuccess = true;
|
|
33
|
+
|
|
34
|
+
for (const rollupConfig of options) {
|
|
35
|
+
if (!(await runRollup(rollupConfig))) {
|
|
36
|
+
isSuccess = false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return isSuccess;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function watchRollup(options: RollupOptions): RollupWatcher {
|
|
44
|
+
const { output, ...input } = options;
|
|
45
|
+
|
|
46
|
+
const watcher = watch({
|
|
47
|
+
...input,
|
|
48
|
+
output,
|
|
49
|
+
watch: {
|
|
50
|
+
clearScreen: false,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
watcher.on("event", (evt) => {
|
|
55
|
+
if (evt.code === "BUNDLE_END" && evt.result) {
|
|
56
|
+
evt.result.close();
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return watcher;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function watchRollups(options: RollupOptions[]): RollupWatcher[] {
|
|
64
|
+
return options.map((rollupConfig) => watchRollup(rollupConfig));
|
|
65
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export class CodeGen {
|
|
2
|
+
private lines: string[] = [];
|
|
3
|
+
|
|
4
|
+
public import(packageName: string, as?: string) {
|
|
5
|
+
if (!as) {
|
|
6
|
+
as = CodeGen.packageNameToProperty(packageName);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return this.add(`import * as ${as} from "${packageName}"`);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public createGlobalObject(scope: string): this {
|
|
13
|
+
return this.add(
|
|
14
|
+
scope
|
|
15
|
+
.split(".")
|
|
16
|
+
.map((s) => s.trim())
|
|
17
|
+
.filter(Boolean)
|
|
18
|
+
.map((_, index, levels) => {
|
|
19
|
+
const path = "window." + levels.slice(0, index + 1).join(".");
|
|
20
|
+
return `${path} = ${path} || {}`;
|
|
21
|
+
})
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public setGlobalObjectProperty(
|
|
26
|
+
scope: string,
|
|
27
|
+
key: string,
|
|
28
|
+
value: string
|
|
29
|
+
): this {
|
|
30
|
+
return this.add(`window.${scope}['${key}'] = ${value}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public static packageNameToProperty(packageName: string): string {
|
|
34
|
+
return packageName
|
|
35
|
+
.replace(/^@/, "")
|
|
36
|
+
.replace(/\//g, "_")
|
|
37
|
+
.replace(/[-_](.)/g, (_, c) => c.toUpperCase())
|
|
38
|
+
.replace(/^[a-z]/, (c) => c.toUpperCase());
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public static renderReactComponentToFile(
|
|
42
|
+
outputFilename: string,
|
|
43
|
+
component: string
|
|
44
|
+
) {
|
|
45
|
+
return `var server = require('react-dom/server');
|
|
46
|
+
var fs = require('node:fs/promises');
|
|
47
|
+
var path = require('node:path');
|
|
48
|
+
const html = server.renderToString( ${component}( {} ) );
|
|
49
|
+
const file = path.resolve(__dirname, '${outputFilename}');
|
|
50
|
+
fs.writeFile(file, html, { flag: "w+" });`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public add(line: string | string[]): this {
|
|
54
|
+
if (Array.isArray(line)) {
|
|
55
|
+
this.lines.push(...line);
|
|
56
|
+
} else {
|
|
57
|
+
this.lines.push(line);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public out(): string {
|
|
64
|
+
return this.lines.join(";\n");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
|
|
3
|
+
export type ConfigOptions = {
|
|
4
|
+
islands: Record<string, string>;
|
|
5
|
+
output: string;
|
|
6
|
+
minify?: boolean;
|
|
7
|
+
ssg?: boolean;
|
|
8
|
+
jsx?: "react" | "react-jsx" | "preserve" | "preserve-react";
|
|
9
|
+
typescript?: boolean;
|
|
10
|
+
common?: string[];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type NormalizedConfigOptions = {
|
|
14
|
+
islands: Record<string, string>;
|
|
15
|
+
output: string;
|
|
16
|
+
minify: boolean;
|
|
17
|
+
ssg: boolean;
|
|
18
|
+
jsx: "react" | "react-jsx" | "preserve" | "preserve-react";
|
|
19
|
+
typescript: boolean;
|
|
20
|
+
common: string[];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type IndividualIslandConfigOptions = Omit<
|
|
24
|
+
NormalizedConfigOptions,
|
|
25
|
+
"islands"
|
|
26
|
+
> & {
|
|
27
|
+
name: string;
|
|
28
|
+
input: string;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export function readConfig(path: string): NormalizedConfigOptions {
|
|
32
|
+
const contents = readFileSync(path, "utf8");
|
|
33
|
+
const json = JSON.parse(contents) as ConfigOptions;
|
|
34
|
+
|
|
35
|
+
return normalizeBuildOptions(json);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function normalizeBuildOptions(
|
|
39
|
+
options: ConfigOptions
|
|
40
|
+
): NormalizedConfigOptions {
|
|
41
|
+
const normalizeBoolean = (
|
|
42
|
+
value: boolean | undefined | null | void,
|
|
43
|
+
fallback: boolean
|
|
44
|
+
): boolean => {
|
|
45
|
+
if (value === false) {
|
|
46
|
+
return false;
|
|
47
|
+
} else if (value === true) {
|
|
48
|
+
return true;
|
|
49
|
+
} else {
|
|
50
|
+
return fallback;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
islands: options.islands,
|
|
56
|
+
output: options.output || "./dist/",
|
|
57
|
+
minify: normalizeBoolean(options.minify, true),
|
|
58
|
+
ssg: normalizeBoolean(options.ssg, true),
|
|
59
|
+
jsx: options.jsx || "react-jsx",
|
|
60
|
+
typescript: normalizeBoolean(options.ssg, false),
|
|
61
|
+
common: options.common || [
|
|
62
|
+
"react",
|
|
63
|
+
"react/jsx-runtime",
|
|
64
|
+
"react-dom/client",
|
|
65
|
+
"@wrdagency/react-islands",
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { exec } from "child_process";
|
|
2
|
+
import { RollupWatcher } from "rollup";
|
|
3
|
+
import { promisify } from "util";
|
|
4
|
+
import yoctoSpinner from "yocto-spinner";
|
|
5
|
+
|
|
6
|
+
const execPromise = promisify(exec);
|
|
7
|
+
|
|
8
|
+
export class Output {
|
|
9
|
+
public line(line: string) {
|
|
10
|
+
console.log(line);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public async spinner(message: string, callback: () => Promise<boolean>) {
|
|
14
|
+
const spinner = yoctoSpinner({
|
|
15
|
+
text: `${message}...`,
|
|
16
|
+
}).start();
|
|
17
|
+
|
|
18
|
+
const success = await callback();
|
|
19
|
+
|
|
20
|
+
if (success) {
|
|
21
|
+
spinner.success(`Succeeded: ${message}`);
|
|
22
|
+
} else {
|
|
23
|
+
spinner.warning(`Failed: ${message}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public watcher(name: string, watcher: RollupWatcher) {
|
|
28
|
+
const spinner = yoctoSpinner({
|
|
29
|
+
text: `Rebuilding ${name}...`,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
let timeAtStart = 0;
|
|
33
|
+
|
|
34
|
+
watcher.on("event", (evt) => {
|
|
35
|
+
if (evt.code === "START") {
|
|
36
|
+
spinner.clear();
|
|
37
|
+
spinner.start();
|
|
38
|
+
timeAtStart = Date.now();
|
|
39
|
+
} else if (evt.code === "END") {
|
|
40
|
+
const timeElapsed = Date.now() - timeAtStart;
|
|
41
|
+
spinner.success(`Rebuilt: ${name} in ${timeElapsed}ms.`);
|
|
42
|
+
} else if (evt.code === "ERROR") {
|
|
43
|
+
spinner.warning(`Failed: ${name}`);
|
|
44
|
+
console.error(evt.error);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public async command(command: string) {
|
|
50
|
+
try {
|
|
51
|
+
const { stdout, stderr } = await execPromise(command);
|
|
52
|
+
|
|
53
|
+
if (stdout) {
|
|
54
|
+
console.log(stdout);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (stderr) {
|
|
58
|
+
console.error(stderr);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return stdout;
|
|
62
|
+
} catch (e) {
|
|
63
|
+
console.error(e);
|
|
64
|
+
throw e;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
package/src/index.tsx
CHANGED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { exec } from "child_process";
|
|
2
|
-
import { promisify } from "util";
|
|
3
|
-
|
|
4
|
-
const execPromise = promisify(exec);
|
|
5
|
-
|
|
6
|
-
export const consoleExecute = async (command: string) => {
|
|
7
|
-
try {
|
|
8
|
-
const { stdout, stderr } = await execPromise(command);
|
|
9
|
-
|
|
10
|
-
if (stdout) {
|
|
11
|
-
console.log(stdout);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
if (stderr) {
|
|
15
|
-
console.error(stderr);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return stdout;
|
|
19
|
-
} catch (e) {
|
|
20
|
-
console.error(e);
|
|
21
|
-
throw e;
|
|
22
|
-
}
|
|
23
|
-
};
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
export function createGlobalObject(namespace: string): string {
|
|
2
|
-
return namespace
|
|
3
|
-
.split(".")
|
|
4
|
-
.filter(Boolean)
|
|
5
|
-
.map((_, index, levels) => {
|
|
6
|
-
const path = "window." + levels.slice(0, index + 1).join(".");
|
|
7
|
-
return `${path} = ${path} || {}`;
|
|
8
|
-
})
|
|
9
|
-
.join(";\n");
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function assignGlobalProperty(
|
|
13
|
-
namespace: string,
|
|
14
|
-
property: string,
|
|
15
|
-
value: string
|
|
16
|
-
): string {
|
|
17
|
-
const namespacing = createGlobalObject(namespace);
|
|
18
|
-
return `${namespacing};\nwindow.${namespace}['${property}'] = ${value};\n`;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function importPackage(packageName: string): string {
|
|
22
|
-
return `import * as ${packageNameToProperty(
|
|
23
|
-
packageName
|
|
24
|
-
)} from "${packageName}";\n`;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function importAndGlobalisePackage(
|
|
28
|
-
packageName: string,
|
|
29
|
-
globalName: string
|
|
30
|
-
): string {
|
|
31
|
-
let str = "";
|
|
32
|
-
|
|
33
|
-
str += importPackage(packageName);
|
|
34
|
-
str += `${globalName} = ${packageNameToProperty(packageName)};\n`;
|
|
35
|
-
|
|
36
|
-
return str;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function packageNameToProperty(packageName: string): string {
|
|
40
|
-
return packageName
|
|
41
|
-
.replace(/^@/, "")
|
|
42
|
-
.replace(/\//g, "_")
|
|
43
|
-
.replace(/[-_](.)/g, (_, c) => c.toUpperCase())
|
|
44
|
-
.replace(/^[a-z]/, (c) => c.toUpperCase());
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function renderComponentToFile(
|
|
48
|
-
filename: string,
|
|
49
|
-
component: string
|
|
50
|
-
): string {
|
|
51
|
-
return `var server = require('react-dom/server');
|
|
52
|
-
var fs = require('node:fs/promises');
|
|
53
|
-
var path = require('node:path');
|
|
54
|
-
const html = server.renderToString( module.exports.component( {} ) );
|
|
55
|
-
const file = path.resolve(__dirname, '${filename}');
|
|
56
|
-
fs.writeFile(file, html, { flag: "w+" });`;
|
|
57
|
-
}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { JsxPreset } from "rollup";
|
|
2
|
-
import { packageNameToProperty } from "./generation";
|
|
3
|
-
|
|
4
|
-
export type BuildOptions = {
|
|
5
|
-
name: string;
|
|
6
|
-
input: string;
|
|
7
|
-
output: string;
|
|
8
|
-
minify?: boolean;
|
|
9
|
-
ssg?: boolean;
|
|
10
|
-
jsx?: JsxPreset;
|
|
11
|
-
typescript?: boolean;
|
|
12
|
-
common?: string[] | Record<string, string>;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export type NormalizedBuildOptions = {
|
|
16
|
-
name: string;
|
|
17
|
-
input: string;
|
|
18
|
-
output: string;
|
|
19
|
-
minify: boolean;
|
|
20
|
-
ssg: boolean;
|
|
21
|
-
jsx: JsxPreset;
|
|
22
|
-
typescript: boolean;
|
|
23
|
-
common: Record<string, string>;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export const normalizeOptions = (
|
|
27
|
-
options: BuildOptions
|
|
28
|
-
): NormalizedBuildOptions => {
|
|
29
|
-
return {
|
|
30
|
-
name: options.name,
|
|
31
|
-
input: options.input,
|
|
32
|
-
output: options.output || "./dist/",
|
|
33
|
-
minify: normalizeBoolean(options.minify, true),
|
|
34
|
-
ssg: normalizeBoolean(options.ssg, true),
|
|
35
|
-
jsx: options.jsx || "react-jsx",
|
|
36
|
-
typescript: normalizeBoolean(options.ssg, false),
|
|
37
|
-
common: normalizeCommonOption(
|
|
38
|
-
options.common || [
|
|
39
|
-
"react",
|
|
40
|
-
"react-dom/client",
|
|
41
|
-
"@wrdagency/react-islands",
|
|
42
|
-
]
|
|
43
|
-
),
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export const normalizeBoolean = (
|
|
48
|
-
value: boolean | undefined | null | void,
|
|
49
|
-
fallback: boolean
|
|
50
|
-
): boolean => {
|
|
51
|
-
if (value === false) {
|
|
52
|
-
return false;
|
|
53
|
-
} else if (value === true) {
|
|
54
|
-
return true;
|
|
55
|
-
} else {
|
|
56
|
-
return fallback;
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
export const normalizeCommonOption = (
|
|
61
|
-
share: BuildOptions["common"] = [""]
|
|
62
|
-
): NormalizedBuildOptions["common"] => {
|
|
63
|
-
if (Array.isArray(share)) {
|
|
64
|
-
return share.reduce(
|
|
65
|
-
(record, packageName) => ({
|
|
66
|
-
...record,
|
|
67
|
-
[packageName]: "Islands._Common." + packageNameToProperty(packageName),
|
|
68
|
-
}),
|
|
69
|
-
{}
|
|
70
|
-
);
|
|
71
|
-
} else {
|
|
72
|
-
return share;
|
|
73
|
-
}
|
|
74
|
-
};
|