sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.57k stars 1.91k forks source link

Can't import from svelte/compiler after Svelte 4 upgrade - build fails with "Cannot find module '../data/patch.json'" error #10799

Open rmunn opened 1 year ago

rmunn commented 1 year ago

Describe the bug

After upgrading a Svelte-Kit project to Svelte 4, it becomes impossible to build the project if you have imported anything from svelte/compiler. The result is an error about "Cannot find module '../data/patch.json'". See below for reproduction steps; to my surprise, the minimal repro involves adding just one line of code to a freshly-created skeleton Svelte-Kit project using Svelte 4.

This is blocking us from upgrading our project to Svelte 4 as we use the svelte/compiler package in one part of our code. We could rewrite that part of the code at considerable effort, but I'd rather just get the build error resolved.

Reproduction

  1. pnpm create svelte@next
  2. Choose skeleton project, answer No to everything else.
  3. pnpm add svelte@4 @sveltejs/kit@1.25.1 to upgrade to Svelte 4
  4. pnpm i (not strictly necessary as pnpm add will take care of it)
  5. Create src/routes/+server.js containing just one line, import { compile } from 'svelte/compiler';
  6. pnpm run build
  7. Build fails with Error: Cannot find module '../data/patch.json'

Logs

> tmp-compiler-repro@0.0.1 build /home/rmunn/code/svelte-compiler-repro
> vite build

vite v4.4.9 building SSR bundle for production...
✓ 1253 modules transformed.

node:internal/event_target:912
  process.nextTick(() => { throw err; });
                           ^
Error: Cannot find module '../data/patch.json'
Require stack:
- /home/rmunn/code/svelte-compiler-repro/.svelte-kit/output/server/entries/endpoints/_server.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
    at Function.Module._load (node:internal/modules/cjs/loader:778:27)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at file:///home/rmunn/code/svelte-compiler-repro/.svelte-kit/output/server/entries/endpoints/_server.js:11564:15
    at ModuleJob.run (node:internal/modules/esm/module_job:198:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:385:24)
    at async analyse (file:///home/rmunn/code/svelte-compiler-repro/node_modules/.pnpm/@sveltejs+kit@1.25.1_svelte@4.2.1_vite@4.4.9/node_modules/@sveltejs/kit/src/core/postbuild/analyse.js:83:16)
    at async MessagePort.<anonymous> (file:///home/rmunn/code/svelte-compiler-repro/node_modules/.pnpm/@sveltejs+kit@1.25.1_svelte@4.2.1_vite@4.4.9/node_modules/@sveltejs/kit/src/utils/fork.js:22:16)
Emitted 'error' event on Worker instance at:
    at Worker.[kOnErrorMessage] (node:internal/worker:289:10)
    at Worker.[kOnMessage] (node:internal/worker:300:37)
    at MessagePort.<anonymous> (node:internal/worker:201:57)
    at MessagePort.[nodejs.internal.kHybridDispatch] (node:internal/event_target:643:20)
    at MessagePort.exports.emitMessage (node:internal/per_context/messageport:23:28) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/home/rmunn/code/svelte-compiler-repro/.svelte-kit/output/server/entries/endpoints/_server.js'
  ]
}
 ELIFECYCLE  Command failed with exit code 1.

System Info

System:
    OS: Linux 5.15 Linux Mint 21 (Vanessa)
    CPU: (12) x64 Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
    Memory: 14.68 GB / 62.56 GB
    Container: Yes
    Shell: 5.1.16 - /bin/bash
  Binaries:
    Node: 16.16.0 - ~/.nvm/versions/node/v16.16.0/bin/node
    Yarn: 1.22.15 - ~/.nvm/versions/node/v16.16.0/bin/yarn
    npm: 8.11.0 - ~/.nvm/versions/node/v16.16.0/bin/npm
    pnpm: 8.6.7 - ~/.local/share/pnpm/pnpm
  Browsers:
    Chromium: 117.0.5938.62
  npmPackages:
    @sveltejs/adapter-auto: ^1.0.0-next.90 => 1.0.3 
    @sveltejs/kit: ^1.25.1 => 1.25.1 
    svelte: ^4.2.1 => 4.2.1 
    vite: ^4.0.0 => 4.4.9

Severity

blocking an upgrade

Additional Information

The ../data/patch.json code in question comes from css-tree, in ./node_modules/.pnpm/css-tree@2.3.1/node_modules/css-tree/lib/data-patch.js. It contains:

import { createRequire } from 'module';

const require = createRequire(import.meta.url);
const patch = require('../data/patch.json');

export default patch;

That code ends up bundled into the _server.js file looking something like this:

const createSyntax$1 = (config) => createSyntax(mix({}, config));
const require$2 = createRequire(import.meta.url);
const patch = require$2("../data/patch.json");
const require$1 = createRequire(import.meta.url);
const mdnAtrules = require$1("mdn-data/css/at-rules.json");
const mdnProperties = require$1("mdn-data/css/properties.json");
const mdnSyntaxes = require$1("mdn-data/css/syntaxes.json");

The relative path in the require call is not being adjusted by the Vite bundling process, so it fails because the current working directory is no longer deep inside the css-tree source (where the data/patch.json file could be found) but rather at the root of the Svelte-Kit project's repo.

rmunn commented 1 year ago

Since the reproduction involves creating a fresh skeleton project, running one pnpm command, and then addding a single line of code, which takes less than a minute to do, it seems silly to create a repro repo that will be around forever with just a single line of code difference from the skeleton Svelte-Kit project. But if that's required, I'll create one.

geoffrich commented 1 year ago

Assuming this is the same issue, @gtm-nayan gave a workaround here: https://github.com/sveltejs/svelte/issues/9288#issuecomment-1748034687

hahn-kev commented 1 year ago

Thanks, I'm not totally sure how his code was suppoed to work. But this worked for me:

{
  resolveId(id: string): string | undefined {
    if (id === 'css-tree') {
      return './node_modules/css-tree/dist/csstree.esm.js';
    }
  }
},
sunnysideup commented 10 months ago

I resolved this by installing:

npm install mdn-data
paulocoghi commented 10 months ago

I'm using Rollup to bundle our code, which uses svelte/compiler, importing it with:

import { compile } from 'svelte/compiler';

Before bundling, everything works fine. But after it, we get the same error informed by OP:

Error: Cannot find module '../data/patch.json'

Update: The error happens both when using npm or pnpm. I even reinstalled everything from scratch with npm only, but the error persists.

Rollup fix Do someone knows how to apply the suggested fix on Rollup config?

paulocoghi commented 10 months ago

I found a solution for anyone using Rollup.

1. Install css-tree and @rollup/plugin-virtual on your dependencies (or devDependencies, if you will)

2. On your configuration file for Rollup, add css-tree as a virtual package before every other plugin:

import virtual          from '@rollup/plugin-virtual';
// ...
import { readFileSync } from 'fs';

export default {
    input: 'your_input_here.js',

    output: {
        file: 'your_output_here.js'
        // ...
        // ...
    },

    plugins: [
        virtual({ 'css-tree': readFileSync('./node_modules/css-tree/dist/csstree.esm.js', 'utf8') }),
        // ...
    ]
};
stearnsbq-aem commented 8 months ago

FWIW the mdsvex plugin also has a compile export that seems to also trigger this issue as well and doing the workarounds for css-tree do not work even though css-tree is in the tree of dependencies and the same code is output in the built app.

aaronjbecker commented 7 months ago

I ran into this same error message while using a package that relies on svelte/compiler in server-side code under adapter-node, and was able to solve it by having rollup treat css-tree as an external dependency. Details/snippets in this issue comment. @stearnsbq-aem I'm curious to know whether this fix addresses your issue with mdsvex since I'm planning to use that soon...

vlimki commented 2 months ago

FWIW the mdsvex plugin also has a compile export that seems to also trigger this issue as well and doing the workarounds for css-tree do not work even though css-tree is in the tree of dependencies and the same code is output in the built app.

Yup. Ran into this as well.

vlimki commented 2 months ago

In case someone is running into the same issue with mdsvex, I solved the problem by simply setting mdsvex as a non-dev dependency.

mechbear14 commented 1 month ago

In case someone is running into the same issue with mdsvex, I solved the problem by simply setting mdsvex as a non-dev dependency.

Thanks. This was my problem as well.

However, in my case, setting mdsvex as a non-dev dependency was incorrect, though it got rid of the error. My site uses compile function when it builds a stats of all .svx pages. The intention was to use the compile function only during build. Therefore it should be a dev dependency and not a runtime dependency.

The error (reads "mistake") was because the module that used compile got imported into a +page.server.js and made it into the runtime. My fix was to put the function into a dedicated folder outside of src for all build-time functions, and make sure they did not get imported anywhere inside src.

Lesson learned: server is a server runtime, not a build environment.

If you're building an app that compiles svx based on user request, then @vlimki is exactly right. In this case, mdsvex is a runtime dependency of the application, and therefore should be set as a non-dev dependency.

dummdidumm commented 1 month ago

The original issue related to css-tree is fixed in Svelte 5, since we're not reyling on that dependency anymore