adonisjs / inertia

Official Inertia.js adapter for AdonisJS
MIT License
92 stars 10 forks source link

Build Error: Inertia not found in build #29

Closed discoverlance-com closed 3 months ago

discoverlance-com commented 4 months ago

Package version

1.1.0

Describe the bug

Sorry, I am not sure whether I should check this in adonisjs core instead...

I am getting a build error, it seems that inertia is not added at all in the build. If you look at the picture below, which is the build, there's no inertia folder at all. And when you cd into the build folder and run npm run start, you get the error: 5:24:40 PM [vite] Pre-transform error: Failed to load url /inertia/app/app.tsx (resolved id: /inertia/app/app.tsx). Does the file exist? and 5:24:40 PM [vite] Pre-transform error: Failed to load url /inertia/pages/home.tsx (resolved id: /inertia/pages/home.tsx). Does the file exist?. Screenshot 2024-06-28 17 22 35

Could it be because in the tsconfig as mentioned in the official inertia docs on adonis website, it ignores the directory where inertia is? I tried to remove inertia/**/* from the exclude option in the tsconfig but it now results in a bunch of errors around react and tsx. It should be using the tsconfig in the inertia folder for the build right?

{
  "compilerOptions": {
    // ...
  },
  "exclude": ["inertia/**/*"]
}

(TSX ERRORS from removing inertia/**/* from the tsconfig after build) image

I deployed the application on fly and I am getting a similar error

{
  "level": 60,
  "time": 1719594306946,
  "pid": 330,
  "hostname": "185e295b425448",
  "request_id": "g91q2v5gbxcf43j79d1aq1mx",
  "err": {
    "type": "EdgeError",
    "message": "Cannot find \"inertia/pages/errors/server_error.tsx\" chunk in the manifest file",
    "stack": "Error: Cannot find \"inertia/pages/errors/server_error.tsx\" chunk in the manifest file\n at anonymous (/app/build/resources/views/inertia_layout.edge:12:0)\n at Template.reThrow (file:///app/node_modules/edge.js/build/chunk-BEFAZY6F.js:523:11)\n at eval (eval at #wrapToFunction (file:///app/node_modules/edge.js/build/index.js:1168:14), <anonymous>:52:10)",
    "code": "E_RUNTIME_EXCEPTION",
    "line": 12,
    "col": 0,
    "filename": "/app/build/resources/views/inertia_layout.edge"
  },
  "msg": "Exception raised by error handler"
}

Reproduction repo

https://github.com/discoverlance-com/adonis-build-error

discoverlance-com commented 4 months ago

I see the issue, I should be running the yarn start command from the root directory.

It was just not working when running from the root directory so that's why. I think it's because the default package.json command for start tries to run the command from bin/server.js, "start": "node bin/server.js", which gives the error: Error: Cannot find module '/workspaces/adonis-build-error/bin/server.js', instead of build/bin/server.js, "start": "node build/bin/server.js". So I have been able to change that at least locally.

Sorry to disturb on this, it just was not clear enough. Thanks.

discoverlance-com commented 4 months ago

Wait I think this error still exists because from the adonis docs,

The compiled output is written inside the ./build directory. If you use Vite, its output will be written inside the ./build/public directory.

Once you have created the production build, you may copy the ./build folder to your production server. From now on, the build folder will be the root of your application.

So this means that the build folder should have the inertia build and should be possible to launch it without having to run it from my root directory as the build folder should have all build files including inertia and the adonis application as the new root.

Do I need to run an extra command to build inertia?

Stancobridge commented 4 months ago

Have you been able to resolve this, if yes, please how, am facing same issue

RomainLanz commented 4 months ago

Have you been able to resolve this, if yes, please how, am facing same issue

Could you let me know if you are running the code in production mode?

NODE_ENV=production node bin/server.js

📚 https://docs.adonisjs.com/guides/views-and-templates/inertia#why-my-production-build-is-not-working-

Stancobridge commented 4 months ago

am getting this error

Cannot find "resources/css/app.css" chunk in the manifest file

first of all the css in resources are not being copied to the resources in build folder. I have to copy it myself, then when I run without NODE_ENV=production it works, but if I use NODE_ENV=production, am getting the error above,

Can there be a documentation on how to build inertia for production

discoverlance-com commented 4 months ago

Have you been able to resolve this, if yes, please how, am facing same issue

Could you let me know if you are running the code in production mode?

NODE_ENV=production node bin/server.js

📚 https://docs.adonisjs.com/guides/views-and-templates/inertia#why-my-production-build-is-not-working-

Yes I did run in production too. It looks like the build does not build or move the inertia folder itself, because if you check in the build folder after build, there's no inertia folder in the build. This is just my assumption but it looks like in this case it's looking for the inertia/pages/* and the files are not found or in the build.

By looking at the buildSteps in src/plugins/vite.ts, it looks like the application is built in build/public/assets so could it be that the vite helper in the layout is not resolving it well? @vite(['inertia/app/app.tsx', inertia/pages/${page.component}.tsx]) and instead is looking for the files in inertia/** even after build?

buildSteps: [
          {
            name: 'build-client',
            description: 'build inertia client bundle',
            config: { build: { outDir: 'build/public/assets/' } },
          },
          {
            name: 'build-ssr',
            description: 'build inertia server bundle',
            config: {
              build: {
                ssr: true,
                outDir: options.ssr.output || 'build/ssr',
                rollupOptions: { input: options.ssr.entrypoint },
              },
            },
          },
        ],
tomgobich commented 3 months ago

Starting from your reproduction repo here: https://github.com/discoverlance-com/adonis-build-error

It seems like the build isn't picking up that your pages are actually in use and omitting them from the final build chunks. You should be seeing your pages split out into chunks like below:

Screenshot 2024-08-05 at 8 47 43 AM

Notice there's a chunk for app, server_error, and not_found

When you omit { eager: true } on your page glob import, the build will now properly pickup an chunk your pages within the build.

createInertiaApp({
  progress: { color: '#5468FF' },

  title: (title) => `${title} - ${appName}`,

  resolve: async (name) => {
    const pages = import.meta.glob('../pages/**/*.tsx') // 👈 no eager: true
    let page = pages[`../pages/${name}.tsx`]
    //@ts-ignore
    page.default.layout = name.startsWith('portal/')
      ? //@ts-ignore
        (p) => <DashboardLayout children={p} />
      : //@ts-ignore
        (p) => <GuestLayout children={p} />
    return page
  },

  setup({ el, App, props }) {
    createRoot(el).render(
      <PrimeReactProvider>
        <App {...props} />
      </PrimeReactProvider>
    )
  },
})

Alternatively, you can use the resolvePageComponent helper

createInertiaApp({
  progress: { color: '#5468FF' },

  title: (title) => `${title} - ${appName}`,

  resolve: async (name) => {
    const page = await resolvePageComponent(
      `../pages/${name}.tsx`,
      import.meta.glob('../pages/**/*.tsx')
    )
    // const pages = import.meta.glob('../pages/**/*.tsx', { eager: true })
    // let page = pages[`../pages/${name}.tsx`]
    //@ts-ignore
    page.default.layout = name.startsWith('portal/')
      ? //@ts-ignore
        (p) => <DashboardLayout children={p} />
      : //@ts-ignore
        (p) => <GuestLayout children={p} />
    return page
  },

  setup({ el, App, props }) {
    createRoot(el).render(
      <PrimeReactProvider>
        <App {...props} />
      </PrimeReactProvider>
    )
  },
})

Making either of these two changes gets your reproduction build working.

discoverlance-com commented 3 months ago

Starting from your reproduction repo here: https://github.com/discoverlance-com/adonis-build-error

It seems like the build isn't picking up that your pages are actually in use and omitting them from the final build chunks. You should be seeing your pages split out into chunks like below: Screenshot 2024-08-05 at 8 47 43 AM Notice there's a chunk for app, server_error, and not_found

When you omit { eager: true } on your page glob import, the build will now properly pickup an chunk your pages within the build.

createInertiaApp({
  progress: { color: '#5468FF' },

  title: (title) => `${title} - ${appName}`,

  resolve: async (name) => {
    const pages = import.meta.glob('../pages/**/*.tsx') // 👈 no eager: true
    let page = pages[`../pages/${name}.tsx`]
    //@ts-ignore
    page.default.layout = name.startsWith('portal/')
      ? //@ts-ignore
        (p) => <DashboardLayout children={p} />
      : //@ts-ignore
        (p) => <GuestLayout children={p} />
    return page
  },

  setup({ el, App, props }) {
    createRoot(el).render(
      <PrimeReactProvider>
        <App {...props} />
      </PrimeReactProvider>
    )
  },
})

Alternatively, you can use the resolvePageComponent helper

createInertiaApp({
  progress: { color: '#5468FF' },

  title: (title) => `${title} - ${appName}`,

  resolve: async (name) => {
    const page = await resolvePageComponent(
      `../pages/${name}.tsx`,
      import.meta.glob('../pages/**/*.tsx')
    )
    // const pages = import.meta.glob('../pages/**/*.tsx', { eager: true })
    // let page = pages[`../pages/${name}.tsx`]
    //@ts-ignore
    page.default.layout = name.startsWith('portal/')
      ? //@ts-ignore
        (p) => <DashboardLayout children={p} />
      : //@ts-ignore
        (p) => <GuestLayout children={p} />
    return page
  },

  setup({ el, App, props }) {
    createRoot(el).render(
      <PrimeReactProvider>
        <App {...props} />
      </PrimeReactProvider>
    )
  },
})

Making either of these two changes gets your reproduction build working.

Thanks, I will try this in a bit.

discoverlance-com commented 3 months ago

Hello @tomgobich, I tried the changes and I went with the second method, it works now as also shown below. Thanks.

createInertiaApp({
  progress: { color: '#5468FF' },

  title: (title) => `${title} - ${appName}`,

  resolve: async (name) => {
    const page = await resolvePageComponent(
      `../pages/${name}.tsx`,
      import.meta.glob('../pages/**/*.tsx')
    )
    //@ts-ignore
    page.default.layout = name.startsWith('portal/')
      ? //@ts-ignore
        (p) => <DashboardLayout children={p} />
      : //@ts-ignore
        (p) => <GuestLayout children={p} />
    return page
  },

  setup({ el, App, props }) {
    createRoot(el).render(
      <PrimeReactProvider>
        <App {...props} />
      </PrimeReactProvider>
    )
  },
})