diff --git a/.changeset/calm-deers-serve.md b/.changeset/calm-deers-serve.md new file mode 100644 index 00000000000..4952af6b2f5 --- /dev/null +++ b/.changeset/calm-deers-serve.md @@ -0,0 +1,54 @@ +--- +'@builder.io/sdk-vue': patch +--- + +Feature: add `@builder.io/sdk-vue/node/init` entry point with `initializeNodeRuntime` export that sets the IVM instance. + +This import should be called in a server-only environment, such as: + +- For using it manually in your Nuxt Pages, in `pages/[...app].vue` add: + + ```html + + + ``` + +- Exported a new Nuxt plugin (`@builder.io/sdk-vue/nuxt-initialize-node-runtime-plugin`) that simplifies setting up the `isolated-vm` in Node.js environments. Here's how you can use it: + + ```ts + // nuxt.config.ts + export default defineNuxtConfig({ + // ... + plugins: ['@builder.io/sdk-vue/nuxt-initialize-node-runtime-plugin'], + }); + ``` + +- Updates to `@builder.io/sdk-vue/nuxt` Nuxt module which helps you achieve this in one place: + + - added `includeCompiledCss` flag that adds the compiled Builder.io CSS in Nuxt (defaults to `true`) + - added `initializeNodeRuntime` flag that executes `nuxt-initialize-node-runtime-plugin` plugin (defaults to `false`) + + ```ts + // nuxt.config.ts + export default defineNuxtConfig({ + // ... + modules: [ + [ + '@builder.io/sdk-vue/nuxt', + { + includeCompiledCss: true, // Includes Builder.io CSS (default: true) + initializeNodeRuntime: true, // Initializes isolated VM in Node runtime (default: false) + }, + ], + ], + }); + ``` diff --git a/packages/sdks/output/vue/README.md b/packages/sdks/output/vue/README.md index ee19685802a..9e0b01c41c8 100644 --- a/packages/sdks/output/vue/README.md +++ b/packages/sdks/output/vue/README.md @@ -13,7 +13,7 @@ NOTE: if you are using Nuxt, you will need to add the SDK's Nuxt module in `nuxt ```js // https://nuxt.com/docs/api/configuration/nuxt-config export default defineNuxtConfig({ - module: ['@builder.io/sdk-vue/nuxt'], + modules: ['@builder.io/sdk-vue/nuxt'], }); ``` diff --git a/packages/sdks/output/vue/nuxt-isolated-vm-plugin.js b/packages/sdks/output/vue/nuxt-isolated-vm-plugin.js new file mode 100644 index 00000000000..d20c783682b --- /dev/null +++ b/packages/sdks/output/vue/nuxt-isolated-vm-plugin.js @@ -0,0 +1,14 @@ +import { defineNuxtPlugin } from 'nuxt/app'; + +export default defineNuxtPlugin((nuxtApp) => { + // initialize Isolated VM on node runtime + if (process.server || import.meta.server) { + async function importIsolatedVM() { + const { initializeNodeRuntime } = await import( + '@builder.io/sdk-vue/node/init' + ); + initializeNodeRuntime(); + } + importIsolatedVM(); + } +}); diff --git a/packages/sdks/output/vue/nuxt.js b/packages/sdks/output/vue/nuxt.js index 59e411a58eb..7dc3c7cfd10 100644 --- a/packages/sdks/output/vue/nuxt.js +++ b/packages/sdks/output/vue/nuxt.js @@ -1,10 +1,39 @@ -import { defineNuxtModule } from '@nuxt/kit'; +import { addPlugin, defineNuxtModule } from '@nuxt/kit'; export default defineNuxtModule({ setup(options, nuxt) { + const includeCompiledCss = options.includeCompiledCss ?? true; + const initializeNodeRuntime = options.initializeNodeRuntime ?? false; /** * Add the compiled Builder.io CSS to the Nuxt CSS array. */ - nuxt.options.css.push('@builder.io/sdk-vue/css'); + if (includeCompiledCss) { + nuxt.options.css.push('@builder.io/sdk-vue/css'); + } + /** + * This is because Vite tries to optimize the isolated-vm dependency while + * running the dev server (first build), which is not needed and throws an error. + * `isolated-vm` is a Node.js native module which should only be imported and used in Node.js environments. + */ + if (initializeNodeRuntime) { + if (nuxt.options.vite?.optimizeDeps?.exclude) { + nuxt.options.vite.optimizeDeps.exclude.push( + '@builder.io/sdk-vue/node/init' + ); + } else { + nuxt.options.vite = { + ...nuxt.options.vite, + optimizeDeps: { + ...nuxt.options.vite?.optimizeDeps, + exclude: ['@builder.io/sdk-vue/node/init'], + }, + }; + } + + addPlugin({ + src: '@builder.io/sdk-vue/nuxt-initialize-node-runtime-plugin', + mode: 'server', + }); + } }, }); diff --git a/packages/sdks/output/vue/package.json b/packages/sdks/output/vue/package.json index 646fca13142..cb090f12413 100644 --- a/packages/sdks/output/vue/package.json +++ b/packages/sdks/output/vue/package.json @@ -13,7 +13,8 @@ }, "files": [ "lib", - "nuxt.js" + "nuxt.js", + "nuxt-isolated-vm-plugin.js" ], "sideEffects": [ "./lib/browser/style.css", @@ -25,6 +26,7 @@ "exports": { "./css": "./lib/browser/style.css", "./nuxt": "./nuxt.js", + "./nuxt-initialize-node-runtime-plugin": "./nuxt-isolated-vm-plugin.js", "./bundle/edge": { "import": "./lib/edge/index.mjs", "require": "./lib/edge/index.cjs" @@ -82,6 +84,10 @@ "import": "./lib/browser/index.mjs", "require": "./lib/browser/index.cjs" } + }, + "./node/init": { + "import": "./lib/node/init.mjs", + "require": "./lib/node/init.cjs" } }, "scripts": { diff --git a/packages/sdks/output/vue/vite.config.js b/packages/sdks/output/vue/vite.config.js index 9eba7eedb56..80694badb7e 100644 --- a/packages/sdks/output/vue/vite.config.js +++ b/packages/sdks/output/vue/vite.config.js @@ -9,6 +9,8 @@ import { resolve } from 'path'; import { defineConfig } from 'vite'; import dts from 'vite-plugin-dts'; +const SDK_ENV = getSdkEnv(); + // https://vitejs.dev/config/ export default defineConfig({ plugins: [ @@ -19,17 +21,27 @@ export default defineConfig({ const outPath = getSdkOutputPath(); copyFileSync(outPath + '/index.d.ts', outPath + '/index.d.mts'); renameSync(outPath + '/index.d.ts', outPath + '/index.d.cts'); + + if (SDK_ENV === 'node') { + copyFileSync(outPath + '/functions/evaluate/node-runtime/init.d.ts', outPath + '/init.d.mts'); + copyFileSync(outPath + '/functions/evaluate/node-runtime/init.d.ts', outPath + '/init.d.cts'); + } }, }), ], build: { lib: { - entry: resolve(__dirname, 'src/index.ts'), + entry: { + index: resolve(__dirname, 'src/index.ts'), + ...(SDK_ENV === 'node' ? { + init: resolve(__dirname, 'src/functions/evaluate/node-runtime/init.ts') + } : {}), + }, formats: ['es', 'cjs'], - fileName: (format) => `index.${format === 'es' ? 'mjs' : 'cjs'}`, + fileName: (format, entryName) => `${entryName}.${format === 'es' ? 'mjs' : 'cjs'}`, }, rollupOptions: { - external: ['vue', 'node:module'], + external: ['vue', 'node:module', 'isolated-vm'], output: { globals: { vue: 'Vue', @@ -39,7 +51,7 @@ export default defineConfig({ * Adding CSS imports to server bundles breaks Nuxt, since `.css` is an invalid extension. * Instead, users should manually import the CSS file for SSR builds. */ - banner: getSdkEnv() === 'browser' ? 'import "./style.css";' : undefined, + banner: SDK_ENV === 'browser' ? 'import "./style.css";' : undefined, }, }, }, diff --git a/packages/sdks/src/functions/evaluate/node-runtime/node-runtime.ts b/packages/sdks/src/functions/evaluate/node-runtime/node-runtime.ts index 7c41d8537bb..70fd0c376cc 100644 --- a/packages/sdks/src/functions/evaluate/node-runtime/node-runtime.ts +++ b/packages/sdks/src/functions/evaluate/node-runtime/node-runtime.ts @@ -95,7 +95,8 @@ export const setIvm = (ivm: IsolatedVMImport, options: IsolateOptions = {}) => { const SHOULD_MENTION_INITIALIZE_SCRIPT = SDK_NAME === '@builder.io/sdk-react-nextjs' || SDK_NAME === '@builder.io/sdk-react' || - SDK_NAME === '@builder.io/sdk-qwik'; + SDK_NAME === '@builder.io/sdk-qwik' || + SDK_NAME === '@builder.io/sdk-vue'; const getIvm = (): IsolatedVMImport => { try {