buildpacks icon indicating copy to clipboard operation
buildpacks copied to clipboard

Trouble when trying to correctly build and run a basic Svelte javascript project

Open jama22 opened this issue 1 year ago • 6 comments

Describe the bug I'm trying to use the GCP buildpacks to build a basic, getting started Svelt app, and I"m running into an issue on the build step

Additional context How are you using GCP buildpacks?

  • [x] pack and the gcr.io/buildpacks/builder

Did this used to work? Nope, probably never worked

What language is your project primarily written in? Nodejs, Svelte framework

Steps To Reproduce

  1. Run the commands to start a basic project here https://kit.svelte.dev/docs/creating-a-project
  2. run pack build my-app --builder gcr.io/buildpacks/builder:google-22
  3. run docker run my-app

Actual Behavior The app correctly builds into an OCI image locally. However, when I try to get the image up and running I get the following error:

node:internal/modules/cjs/loader:1147
  throw err;
  ^

Error: Cannot find module '/workspace/index.js'
    at Module._resolveFilename (node:internal/modules/cjs/loader:1144:15)
    at Module._load (node:internal/modules/cjs/loader:985:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)
    at node:internal/main/run_main_module:28:49 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

Actual behavior It should just work

jama22 avatar Feb 09 '24 20:02 jama22

@jama22 I don't think it should "just work". I reprod and looking at the package.json, it is missing a start command.

"scripts": {
		"dev": "vite dev",
		"build": "vite build",
		"preview": "vite preview",
		"check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
		"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch"
	},

Since it is missing a start command, our buildpacks configures the entrypoint because npm run dev is not suitable for a production environment.

kennethye1 avatar Feb 23 '24 22:02 kennethye1

@lukasberger we're out of our depth here on Svelte-kit, what's a good way to stand up a server to run a Svelte app? Just doing some digging, it seems like Svelte uses adaptors https://kit.svelte.dev/docs/adapter-node

jama22 avatar Feb 23 '24 23:02 jama22

I agree that we shouldn't use "dev". I'm not familiar enough with Sveltekit to know, but I think "preview" might be the recommended way?

Can we hold off on closing this issue for the moment while we look into it?

LukeSchlangen avatar Feb 23 '24 23:02 LukeSchlangen

Yeah, for sure we'll leave this issue open until we find a reasonable way to get Sveltkit up and running

jama22 avatar Feb 24 '24 01:02 jama22

After more exploration, I now agree with @kennethye1. Working with SvelteKit's node-adapter docs, this was the shortest path I could find to deploying a SvelteKit application out of the box.

  1. npm create svelte@latest sveltekit-app
  2. cd sveltekit-app
  3. npm i -D @sveltejs/adapter-node
  4. npm uninstall -D @sveltejs/adapter-auto
  5. npm pkg set scripts.start="node build"
  6. Change auto to node in svelte.config.js
  7. gcloud run deploy

I think we can likely close this for now and consider reopening if this ever gets easier.

LukeSchlangen avatar Mar 06 '24 19:03 LukeSchlangen

TL;DR

The SvelteKit team seems open to a change that would allow us to deploy SvelteKit applications out of the box if Cloud Buildpacks can:

  1. Detect a SvelteKit application
  2. Add a unique environment variable to the Cloud Build environment before the standard npm run build step

The much longer story

The SvelteKit team has shown an openness to accepting an adapter that would make Cloud Run work if we give them the name of an environment variable that they can detect: https://github.com/sveltejs/kit/issues/11951

SvelteKit has the concept of using different adapters that generate different outputs for different target environments. You can select your adapter (like adapter-node for Cloud Run), but SvelteKit also has the concept of a zero-config adapter-auto which is the default for new projects. The automatic adapter selects which adapter to use based on the environment variable present. So for default projects, the steps are:

  1. adapter-auto runs through this code to check for the existence of environment variables like VERCEL or a logical check like process.env.GITHUB_ACTION_REPOSITORY === 'Azure/static-web-apps-deploy'
  2. If it finds one that matches, it will pull down that npm package (like @sveltejs/adapter-vercel for Vercel). This is where our deployment currently fails. Our deployment succeeds if you configure the adapter for node servers (adapter-node).
  3. Builds the output as described by the adapter

The adapter package is a dev dependency and is only required during the build (not during the runtime). So we could essentially add a "Step 0" to this list that detects if this is a SvelteKit application: if it contains svelte.config.js. Additional confirmation to use the node adapter could be if @sveltejs/adapter-auto is a dev dependency in package.json or if the string @sveltejs/adapter-auto exists in svelte.config.js. This detection could be similar to this recent Buildpacks change to support Nuxt.js. Then add the environment variable during the build. The variable could be something like USE_SVELTEKIT_NODE_ADAPTER or SVELTEKIT_ADAPTER_NODE.

Another option, if we thought we might end up supporting more adapters like adapter-static would be to create a variable like SVELTEKIT_ADAPTER and then to a test like process.env.SVELTEKIT_ADAPTER === 'adapter-node'.

If we got this working, that would take the number of steps required to deploy a SvelteKit application from seven down to four (or even three)!

Current steps:

  1. npm create svelte@latest sveltekit-app
  2. cd sveltekit-app
  3. npm i -D @sveltejs/adapter-node
  4. npm uninstall -D @sveltejs/adapter-auto
  5. Change auto to node in svelte.config.js
  6. npm pkg set scripts.start="node build"
  7. gcloud run deploy --allow-unauthenticated

Possible future steps:

  1. npm create svelte@latest sveltekit-app
  2. cd sveltekit-app
  3. npm pkg set scripts.start="node build" (might not be necessary if we can add this to the start script)
  4. gcloud run deploy --allow-unauthenticated

LukeSchlangen avatar Mar 13 '24 01:03 LukeSchlangen

@jinglundong - The SvelteKit maintainers would prefer that our environment variable stay specific to Cloud Run (Link to conversation).

  1. Detect a SvelteKit Application
    • Contains svelte.config.js file
    • Check package.json for confirmation:
      • @sveltejs/adapter-auto is a dependency
      • npm start is not defined
  2. Add an environment variable unique to Google Cloud Buildpacks
    • I suggest GOOGLE_CLOUD_BUILDPACKS, but it could be anything the team prefers
    • I can make the pull request to have this bring in the @sveltejs/adapter-node once we confirm the environment variable name
  3. Run npm run build (Shouldn't require any changes since this is standard for Node.js projects)
  4. Set the start command to node build

LukeSchlangen avatar Mar 20 '24 01:03 LukeSchlangen