BuilderIO / builder

Visual Development for React, Vue, Svelte, Qwik, and more
https://builder.io
MIT License
7.27k stars 897 forks source link

"isolated-vm import error" on Vercel with Nuxt 3 #3288

Open 20x-dz opened 4 months ago

20x-dz commented 4 months ago

Describe the bug I see the following errors in the Vercel log after visiting a builder.io page (the page seems to render fine though):

[Builder.io]:  isolated-vm import error. Error: Cannot find module 'isolated-vm'
Require stack:
- /var/task/node_modules/@builder.io/sdk-vue/lib/node/index-551oCh4n.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1140:15)
    at Module._load (node:internal/modules/cjs/loader:981:27)
    at /opt/rust/nodejs.js:1:11508
    at Function.Qt (/opt/rust/nodejs.js:1:11878)
    at Q.e.<computed>.K._load (/opt/rust/nodejs.js:1:11478)
    at Module.require (node:internal/modules/cjs/loader:1231:19)
    at require (node:internal/modules/helpers:177:18)
    at getIvm (file:///var/task/node_modules/@builder.io/sdk-vue/lib/node/index-551oCh4n.js:318:15)
    at runInNode (file:///var/task/node_modules/@builder.io/sdk-vue/lib/node/index-551oCh4n.js:350:13)
    at chooseBrowserOrServerEval (file:///var/task/node_modules/@builder.io/sdk-vue/lib/node/index-551oCh4n.js:391:108) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/var/task/node_modules/@builder.io/sdk-vue/lib/node/index-551oCh4n.js'
  ]
}

followed by

[Builder.io]:  Failed code evaluation: [Builder.io]: could not import `isolated-vm` module for safe script execution on Node server.

    In certain Node environments, the SDK requires additional initialization steps. This can be achieved by 
    importing and calling `initializeNodeRuntime()` from "@builder.io/sdk-react/node/init". This must be done in
    a server-only execution path within your application.

    Please see the documentation for more information: https://builder.io/c/docs/integration-tips#enabling-data-bindings-in-node-environments
     {
  code: 'var __awaiter=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function a(e){try{c(r.next(e))}catch(e){o(e)}}function u(e){try{c(r.throw(e))}catch(e){o(e)}}function c(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(a,u)}c((r=r.apply(e,t||[])).next())}))},__generator=function(e,t){var n,r,i,o,a={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:u(0),throw:u(1),return:u(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function u(o){return function(u){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return a.label++,{value:o[1],done:!1};case 5:a.label++,r=o[1],o=[0];continue;case 7:o=a.ops.pop(),a.trys.pop();continue;default:if(!(i=(i=a.trys).length>0&&i[i.length-1])&&(6===o[0]||2===o[0])){a=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){a.label=o[1];break}if(6===o[0]&&a.label<i[1]){a.label=i[1],i=o;break}if(i&&a.label<i[2]){a.label=i[2],a.ops.push(o);break}i[2]&&a.ops.pop(),a.trys.pop();continue}o=t.call(e,a)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,u])}}};function main(){return __awaiter(this,void 0,void 0,(function(){var e,t,n;return __generator(this,(function(r){return Builder.isServer,Builder.isBrowser&&(e=document.getElementById("toggleSwitch"),t=document.getElementById("price"),n=document.getElementById("membership-link"),e.addEventListener("change",(function(){this.checked?(t.textContent="0000",n.href="https://example.com"):(t.textContent="0000",n.href="https://example.com")}))),[2]}))}))}var _virtual_index=main();return _virtual_index'
}

The link provided in the 2nd error message only provides a solution for Next.js (React), not for Nuxt (Vue).

To Reproduce Steps to reproduce the behavior:

  1. Visit our page
  2. see the errors in the log

Expected behavior No errors in the logs?

Screenshots

image

Additional context Happens on @builder.io/sdk-vue v1.0.22 as well as v1.0.27 (latest version) on the current Nuxt3 release.

Our main page template ([...slug].vue) loading the content:

<template>
  <div>
    <div v-if="content || isPreviewing()">
      <Content
        model="page"
        :can-track="false"
        :content="content"
        :api-key="builderApiKey"
        :custom-components="REGISTERED_COMPONENTS" />
    </div>
  </div>
</template>

<script setup>
import { Content, fetchOneEntry, isPreviewing } from "@builder.io/sdk-vue";
import FaqItems from "~/components/block/FaqItems.vue";
import Drawer from "~/components/builder.io/Drawer.vue";
import { useCustomHead } from "~/composables/useCustomHead";

// Register your Builder components
const REGISTERED_COMPONENTS = [
  {
    canHaveChildren: false,
    component: FaqItems,
    inputs: [
      {
        name: "faqItems",
        required: true,
        type: "object",
      },
      {
        name: "title",
        type: "text",
      },
    ],
    name: "BlockFaqItems",
  },
  {
    canHaveChildren: true,
    component: Drawer,
    inputs: [
      {
        name: "id",
        required: true,
        type: "text",
      },
    ],
    name: "Drawer",
  },
];

const config = useRuntimeConfig();
const builderApiKey = ref(config.public.builderApiToken);
const isDev = import.meta.dev;
// the app url is also set to example.com on preview environments
const isStaging = config.public.appUrl === "https://example.com";

const route = useRoute();

// fetch builder content data
const { data: content } = await useAsyncData("builderData", () =>
  fetchOneEntry({
    apiKey: builderApiKey.value,
    model: "page",
    options: {
      includeUnpublished: isPreviewing() || isDev || isStaging,
    },
    userAttributes: {
      urlPath: route.path,
    },
  }),
);

if (content.value === null) {
  throw createError({
    fatal: true,
    statusCode: 404,
    statusMessage: "Page Not Found",
  });
}

useCustomHead({
  metaDescription: content.value.data.description,
  metaImage: {
    data: {
      attributes: {
        url: content.value.data.previewImage,
      },
    },
  },
  metaTitle: content.value.data.title,
});
</script>
samijaber commented 4 months ago

Thanks for filing. We will investigate and let you know when we have a fix.

20x-dz commented 2 months ago

Sorry for the ping, any updates on this @samijaber ? Still seeing this logs even with the latest vue-sdk:

[Builder.io]:  isolated-vm import error. Error: Cannot find module 'isolated-vm'
Require stack:
- /var/task/node_modules/@builder.io/sdk-vue/lib/node/index-xwOams1O.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1145:15)
    at Module._load (node:internal/modules/cjs/loader:986:27)
    at /opt/rust/nodejs.js:1:11508
    at Function.$t (/opt/rust/nodejs.js:1:11878)
    at K.e.<computed>.J._load (/opt/rust/nodejs.js:1:11478)
    at Module.require (node:internal/modules/cjs/loader:1233:19)
    at Hook._require.Module.require (/var/task/node_modules/require-in-the-middle/index.js:167:34)
    at require (node:internal/modules/helpers:179:18)
    at getIvm (file:///var/task/node_modules/@builder.io/sdk-vue/lib/node/index-xwOams1O.js:314:15)
    at runInNode (file:///var/task/node_modules/@builder.io/sdk-vue/lib/node/index-xwOams1O.js:346:13) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/var/task/node_modules/@builder.io/sdk-vue/lib/node/index-xwOams1O.js'
  ]
}
[Builder.io]:  Failed code evaluation: [Builder.io]: could not import `isolated-vm` module for safe script execution on Node server.

    In certain Node environments, the SDK requires additional initialization steps. This can be achieved by 
    importing and calling `initializeNodeRuntime()` from "@builder.io/sdk-react/node/init". This must be done in
    a server-only execution path within your application.

    Please see the documentation for more information: https://builder.io/c/docs/integration-tips#enabling-data-bindings-in-node-environments
     {
  code: 'var __awaiter=function(t,e,n,r){return new(n||(n=Promise))((function(a,o){function i(t){try{u(r.next(t))}catch(t){o(t)}}function l(t){try{u(r.throw(t))}catch(t){o(t)}}function u(t){var e;t.done?a(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(i,l)}u((r=r.apply(t,e||[])).next())}))},__generator=function(t,e){var n,r,a,o,i={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]};return o={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function l(o){return function(l){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;i;)try{if(n=1,r&&(a=2&o[0]?r.return:o[0]?r.throw||((a=r.return)&&a.call(r),0):r.next)&&!(a=a.call(r,o[1])).done)return a;switch(r=0,a&&(o=[2&o[0],a.value]),o[0]){case 0:case 1:a=o;break;case 4:return i.label++,{value:o[1],done:!1};case 5:i.label++,r=o[1],o=[0];continue;case 7:o=i.ops.pop(),i.trys.pop();continue;default:if(!(a=(a=i.trys).length>0&&a[a.length-1])&&(6===o[0]||2===o[0])){i=0;continue}if(3===o[0]&&(!a||o[1]>a[0]&&o[1]<a[3])){i.label=o[1];break}if(6===o[0]&&i.label<a[1]){i.label=a[1],a=o;break}if(a&&i.label<a[2]){i.label=a[2],i.ops.push(o);break}a[2]&&i.ops.pop(),i.trys.pop();continue}o=e.call(t,i)}catch(t){o=[6,t],r=0}finally{n=a=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,l])}}};function main(){var t,e,n,r,a;return __awaiter(this,void 0,void 0,(function(){var o,i;return __generator(this,(function(l){return Builder.isServer,Builder.isBrowser&&((o=null===(a=null===(r=null===(n=null===(e=null===(t=state.margit.data)||void 0===t?void 0:t.attributes)||void 0===e?void 0:e.avatar)||void 0===n?void 0:n.data)||void 0===r?void 0:r.attributes)||void 0===a?void 0:a.url)?(i="https://example.com".concat(o),console.log(i)):console.error("Avatar URL is not available")),[2]}))}))}var _virtual_index=main();return _virtual_index'
}

And builder support is not very helpful in this regard… 😅

Crease29 commented 2 months ago

If it helps anyone: A workaround for me was to wrap the BuilderContent in <client-only></client-only>.

20x-dz commented 1 month ago

If it helps anyone: A workaround for me was to wrap the BuilderContent in <client-only></client-only>.

This sadly isn't an option for us because we would lose all the SSR advantages.

Crease29 commented 1 month ago

If it helps anyone: A workaround for me was to wrap the BuilderContent in <client-only></client-only>.

This sadly isn't an option for us because we would lose all the SSR advantages.

Understandable. For me it was enough to only wrap that one component into client-only that was causing the issue.

20x-dz commented 3 weeks ago

This is still an issue. I tried to apply the react suggestions somehow, but to no avail, as isolated-vm does not seem to be available on vercel as I get the following error:

[info] ✓ 544 modules transformed.
Error:  x Build failed in 6.[48](https://github.com/<redacted>/<redacted>/actions/runs/10474377917/job/29009054444#step:5:49)s
Error:  Nuxt Build Error: Could not resolve "./out/isolated_vm" from "./out/isolated_vm?commonjs-external"
file: ./out/isolated_vm?commonjs-external
  file: ./out/isolated_vm?commonjs-external
  at getRollupError (node_modules/rollup/dist/es/shared/parseAst.js:392:41)
  at error (node_modules/rollup/dist/es/shared/parseAst.js:388:42)
  at ModuleLoader.handleInvalidResolvedId (node_modules/rollup/dist/es/shared/node-entry.js:19071:24)
  at node_modules/rollup/dist/es/shared/node-entry.js:19031:26
Error: Command "npm run build" exited with 1

when trying to load isolated-vm conditionally using a composable, e.g.

import { Builder } from "@builder.io/sdk-vue";

export async function useIsolatedVm(): void {
  if (Builder.isServer) {
    await import("isolated-vm");
  }
}

@samijaber any hints?

20x-dz commented 3 weeks ago

And trying import { initializeNodeRuntime } from "@builder.io/sdk-vue/node/init"; doesn't work either because [plugin:vite:import-analysis] Missing "./node/init" specifier in "@builder.io/sdk-vue" package

20x-dz commented 3 weeks ago

importing isolated-vm doesn't work locally either… NODE_OPTIONS=--no-node-snapshot npm run dev on node v20.15.1:

✘ [ERROR] Could not resolve "./out/isolated_vm"

    node_modules/isolated-vm/isolated-vm.js:1:25:
      1 │ module.exports = require('./out/isolated_vm').ivm;
        ╵                          ~~~~~~~~~~~~~~~~~~~

 ERROR  error while updating dependencies:                                                                                                     09:42:25
Error: Build failed with 1 error:
node_modules/isolated-vm/isolated-vm.js:1:25: ERROR: Could not resolve "./out/isolated_vm"
    at failureErrorWithLog (/Users/me/project/frontend/node_modules/esbuild/lib/main.js:1472:15)
    at /Users/me/project/frontend/node_modules/esbuild/lib/main.js:945:25
    at /Users/me/project/jupiter/frontend/node_modules/esbuild/lib/main.js:1353:9
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
maxsolovev commented 1 week ago

@20x-dz please tell me which package manager you use?

20x-dz commented 1 week ago

@20x-dz please tell me which package manager you use?

npm

maxsolovev commented 1 week ago

npm

I use bun and had the same problem. Solved it by adding packages to trustedDependencies (https://bun.sh/guides/install/trusted). Maybe npm has something similar.

20x-dz commented 1 week ago

Thx. This seems to be more of a security measure from bun:

Unlike other npm clients, Bun does not execute arbitrary lifecycle scripts for installed dependencies, such as postinstall and node-gyp builds. These scripts represent a potential security risk, as they can execute arbitrary code on your machine.

To my knowledge npm just executes everything… 😅

And locally (or in a dockerized) we don't have any issues, just on vercel… And vercel support doesn't know anything about this dependency either, which makes everything super frustrating.

maxsolovev commented 1 week ago

Maybe you can try something like this https://github.com/nuxt/vercel-builder/issues/371#issuecomment-804474999

20x-dz commented 1 week ago

Thank you very much for the suggestion, but that seems to be for Nuxt 2 unfortunately.