sveltejs / kit

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

issue with using CommonJS modules in "svelte/kit build" #928

Closed henryennis closed 3 years ago

henryennis commented 3 years ago

App runs normally while running in dev mode, error is thrown on build

svelte.config.cjs

Note the package causing this issue is set to be converted to esm as of the:

optimizeDeps: {
                include: ['carbon-components-svelte', 'clipboard-copy']
                },

svelte.config.cjs

const sveltePreprocess = require('svelte-preprocess');
const node = require('@sveltejs/adapter-node');
const pkg = require('./package.json');

/** @type {import('@sveltejs/kit').Config} */
module.exports = {
    // Consult https://github.com/sveltejs/svelte-preprocess
    // for more information about preprocessors
    preprocess: sveltePreprocess(),
    kit: {
        // By default, `npm run build` will create a standard Node app.
        // You can create optimized builds for different platforms by
        // specifying a different adapter
        adapter: node(),
        ssr: false,
        // hydrate the <div id="svelte"> element in src/app.html
        target: '#svelte',

        vite: {
            // optimizeDeps: {
            //  include: ['carbon-components-svelte', 'clipboard-copy']
            //   },
            ssr: {
                noExternal: Object.keys(pkg.dependencies || {})
            },
            plugins: [
                require('vite-plugin-windicss').default()
              ]
        }
    }
};

importing modules from a commonJS package "carbon-components-svelte" like so:

index.svelte

<script>
  import {
    FluidForm,
    TextInput,
    PasswordInput, Tile
  } from "carbon-components-svelte";
import ButtonFullBleed from "../components/buttons/buttonFullBleed.svelte"
</script>

error

PS C:\Users\henry\sveltekit-dashboard> npm run build

> sveltekit-dashboard@0.0.1 build C:\Users\henry\sveltekit-dashboard
> svelte-kit build

vite v2.1.5 building for production...
✓ 320 modules transformed.
.svelte/output/client/_app/manifest.json                            0.67kb
.svelte/output/client/_app/chunks/index-4d122fc8.js                 5.48kb / brotli: 2.12kb
.svelte/output/client/_app/assets/pages\index.svelte-802f02f9.css   4.19kb / brotli: 0.85kb
.svelte/output/client/_app/start-fbcbe901.js                        15.83kb / brotli: 5.41kb
.svelte/output/client/_app/pages\index.svelte-97280b82.js           59.90kb / brotli: 15.52kb
.svelte/output/client/_app/assets/start-9caedf08.css                459.55kb / brotli: 37.33kb
vite v2.1.5 building SSR bundle for production...
✓ 17 modules transformed.
.svelte/output/server/app.js   544.67kb

Run npm start to try your app locally.

> Using @sveltejs/adapter-node
> Named export 'FluidForm' not found. The requested module 'carbon-components-svelte' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'carbon-components-svelte';
const {FluidForm} = pkg;

file:///C:/Users/henry/sveltekit-dashboard/.svelte/output/server/app.js:8
import {FluidForm} from "carbon-components-svelte";
SyntaxError: Named export 'FluidForm' not found. The requested module 'carbon-components-svelte' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'carbon-components-svelte';
const {FluidForm} = pkg;

    at ModuleJob._instantiate (internal/modules/esm/module_job.js:98:21)
    at async ModuleJob.run (internal/modules/esm/module_job.js:143:5)
    at async Loader.import (internal/modules/esm/loader.js:165:24)
    at async prerender (file:///C:/Users/henry/sveltekit-dashboard/node_modules/@sveltejs/kit/dist/chunks/index6.js:513:14)
    at async AdapterUtils.prerender (file:///C:/Users/henry/sveltekit-dashboard/node_modules/@sveltejs/kit/dist/chunks/index6.js:745:4)
    at async adapt (C:\Users\henry\sveltekit-dashboard\node_modules\@sveltejs\adapter-node\index.js:26:4)
    at async adapt (file:///C:/Users/henry/sveltekit-dashboard/node_modules/@sveltejs/kit/dist/chunks/index6.js:767:2)
    at async file:///C:/Users/henry/sveltekit-dashboard/node_modules/@sveltejs/kit/dist/cli.js:633:5

Note that:

The same issue happens when a Svelte component that imports a CommonJS module is imported in to a vanilla JS Vite project.

You can see the issue for yourselves by importing and instantiating the svelte-nano-donate component at this commit: small-tech/svelte-nano-donate@0d7bcf9 (works, QRious library is inlined) and the one before it (doesn’t work, QRious library is imported from node modules). Note that the second one will also work if you npm install the component via a local file path instead of from npm (I thought everything was fine until I tried to install the component in a Vite/SvelteKit project via npm). (I’m going to go check on the Vite project to see if there are any related issues as we cannot be the first ones to get bitten by this.)

Credit: aral


other information Node version: v14.15.0 OS: windows 10 10.0, build 19041

aral commented 3 years ago

Seeing the same thing on build. Also seems to manifest as a 500 import not found: default error on npm run dev if a svelte component that uses a CommonJS module is installed from npm (works correctly if installed via a local file reference). Happy to open a separate issue for that but it feels like they’re the same one.

henryennis commented 3 years ago

Seeing the same thing on build. Also seems to manifest as a 500 import not found: default error on npm run dev if a svelte component that uses a CommonJS module is installed from npm (works correctly if installed via a local file reference). Happy to open a separate issue for that but it feels like they’re the same one.

I will adapt the post accordingly

aral commented 3 years ago

I will adapt the post accordingly

Note that:

  1. The same issue happens when a Svelte component that imports a CommonJS module is imported in to a vanilla JS Vite project.

  2. You can see the issue for yourselves by importing and instantiating the svelte-nano-donate component at this commit: https://github.com/small-tech/svelte-nano-donate/commit/0d7bcf90407ed33ed9f55a066343cbb3ff63ca98 (works, QRious library is inlined) and the one before it (doesn’t work, QRious library is imported from node modules). Note that the second one will also work if you npm install the component via a local file path instead of from npm (I thought everything was fine until I tried to install the component in a Vite/SvelteKit project via npm).

(I’m going to go check on the Vite project to see if there are any related issues as we cannot be the first ones to get bitten by this.)

benmccann commented 3 years ago

I would suggest trying all the tips in https://github.com/sveltejs/kit/blob/master/documentation/faq/70-packages.md as a first step

Unfortunately, CommonJS is somewhat of a known pain point with Vite at the moment: https://github.com/vitejs/vite/issues/2579

aral commented 3 years ago

@benmccann That’s hugely useful, thank you.

tolu commented 3 years ago

Just had the same issue and weirdly this solution from layercake issue tracker 👇 worked for me (but with @sanity/client dependency that needs prebundling)

Move vite config to own file vite.config.cjs so that

// vite.config.cjs
const pkg = require('./package.json');

/** @type {import('vite').UserConfig} */
export default {
  ssr: {
    noExternal: Object.keys(pkg.dependencies || {})
  },
};
// svelte.config.cjs
const sveltePreprocess = require('svelte-preprocess');
const node = require('@sveltejs/adapter-node');

/** @type {import('@sveltejs/kit').Config} */
module.exports = {
  preprocess: sveltePreprocess(),
  kit: {
    adapter: node(),
    target: '#svelte',

    // vite: {
    /* moved to vite.config.cjs */
    // }
  }
};
henryennis commented 3 years ago

weirdly this solution from layercake issue tracker 👇 worked for me (with @sanity/client dependency)

Move vite config to own file vite.config.cjs so that


// vite.config.cjs

const pkg = require('./package.json');

/** @type {import('vite').UserConfig} */

export default {

  ssr: {

    noExternal: Object.keys(pkg.dependencies || {})

  },

};

Are u saying to seperate vite config from svelte config cjs?

tolu commented 3 years ago

Are u saying to seperate vite config from svelte config cjs?

Yes, at least that worked for me 👍 I'll update my original comment to be more clear!

RemyDekor commented 3 years ago

I'm not sure I understand how noExternal is supposed to work, but just removing the vite config from the svelte.config.cjs worked for me

benmccann commented 3 years ago

The original issue description referred to carbon-components-svelte. For that library, I'm going to close this in favor of https://github.com/vitejs/vite/issues/3024

For other libraries, the couple I tested seem to have been fixed by removing noExternal from the default template

If people are still having issues, please file a new issue with the specific library you're using and steps to reproduce or a repo that reproduces the issue

sjmcdowall commented 3 years ago

@benmccann -- Sorry to post to a closed issue -- but I have no idea if this is related or not at all . I am trying to use Antony's svelte-mapbox in my new Sveltekit app -- and as soon as I uncomment out the import Map statement -- I am getting a 500 error in the browser --

The requested module '/node_modules/fastq/queue.js?v=0e439b33' does not provide an export named 'default'

SyntaxError: The requested module '/node_modules/fastq/queue.js?v=0e439b33' does not provide an export named 'default'

Is this similar or different than this issue? I tried the vite noExternal thing above but that didn't change anything ... TIA!

/Steve

benmccann commented 3 years ago

@sjmcdowall there's an issue over in that repo that describes how to use it with SvelteKit: https://github.com/beyonk-adventures/svelte-mapbox/issues/44

sjmcdowall commented 3 years ago

@benmccann -- Thank you! Sort of embarrassed I didn't see that myself. Cheers!

ecstrema commented 3 years ago

For the original issue, it can be resolved (partly) by using the carbon's import preprocessor, since it avoids going through index.js

praveenkpatare commented 2 years ago

Facing the same issue with jsonwebtoken library.. here is the screnshot of the error --

image

benmccann commented 2 years ago

We'll work on improved CJS support for Vite. But in the meantime see https://github.com/auth0/node-jsonwebtoken/issues/785 https://github.com/auth0/node-jsonwebtoken/issues/655 to improve that library

brgrz commented 2 years ago

Facing the same issue with nanoid, specifically importing strings from nanoid-dictionary.

SyntaxError: Named export 'nolookalikes' not found. The requested module 'nanoid-dictionary' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:
import pkg from 'nanoid-dictionary';
const { nolookalikes } = pkg;
import { customAlphabet } from 'nanoid';
import { nolookalikes } from 'nanoid-dictionary';
export const nanoid = customAlphabet(nolookalikes, 10);

nanoid and nanoid-dictionary both export as ES. https://github.com/CyberAP/nanoid-dictionary#nolookalikes

gavinr commented 2 years ago

I'm getting this same issue with chart.js - they properly have their ESM as the "module" property, so I'm not sure why it's erroring when I'm using adapter-static.

SuspiciousLookingOwl commented 2 years ago

I'm getting this same issue with chart.js - they properly have their ESM as the "module" property, so I'm not sure why it's erroring when I'm using adapter-static.

Have you found the solution?

benmccann commented 2 years ago

Here's an issue about chart.js: https://github.com/chartjs/Chart.js/issues/9436

gavinr commented 2 years ago

I proposed https://github.com/chartjs/Chart.js/pull/9597 .... I think it's the same thing that you were proposing in https://github.com/chartjs/Chart.js/issues/9436 @benmccann

Marcosaurios commented 2 years ago

Any news about this? I am using latest adapter-static and facing the same issue, but in this case with style-value-types dependency (used in svelte-motion)...

> Using @sveltejs/adapter-static
> Named export 'px' not found. The requested module 'style-value-types' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'style-value-types';
const { number, px, degrees, scale, alpha, progressPercentage, complex, color, filter, percent, vw, vh } = pkg;

Edit: Apparently adding the failing dependencies to SSR noExternal property of vite config, make it work, as @benmccann said before:

Here's an issue about chart.js: chartjs/Chart.js#9436

In the svelte.config.js:

const config = {
 kit: {
  vite: {
   ssr: {
    noExternal: ['style-value-types', 'popmotion', 'framesync']
   }
  }
 }
}
benmccann commented 2 years ago

That library is using an old version of style-value-types. Here's a PR to upgrade it: https://github.com/micha-lmxt/svelte-motion/pull/10. I didn't test if it solves the issue you're having, but it's possible it does since it updates the exports map

Marcosaurios commented 2 years ago

@benmccann thank you so much for that! 👏✌️

ogrotten commented 2 years ago

Edit: Apparently adding the failing dependencies to SSR noExternal property of vite config, make it work, as @benmccann said before:

This is the solution that worked for me.

ssr: {
    noExternal: ["svelte-hero-icons", '@googlemaps/js-api-loader'],
},
BillBuilt commented 2 years ago

Edit: Apparently adding the failing dependencies to SSR noExternal property of vite config, make it work, as @benmccann said before:

I was having this exact issue with @fortawesome icons and this fixed it

ssr: {
    noExternal: ['@fortawesome/free-brands-svg-icons', '@fortawesome/free-regular-svg-icons', '@fortawesome/free-solid-svg-icons']
},
benmccann commented 2 years ago

A better solution for icon libraries is to use this option for performance reasons: https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/config.md#prebundlesveltelibraries

BillBuilt commented 2 years ago

Hi, thanks for the tip! Unfortunately, unless I am doing it wrong, this has no effect. Is this supposed to be uses in addition to the ssr.noExternal setting?

/** @type {import('@sveltejs/kit').Config} */
const config = {
    // Consult https://github.com/sveltejs/svelte-preprocess
    // for more information about preprocessors
    preprocess: preprocess(),

    kit: {
        adapter: adapter(),
        vite: {
            experimental: {
                prebundleSvelteLibraries: true
            },
            resolve: {
                alias: {
                    $lib: path.resolve('./src/lib'),
                    $comp: path.resolve('./src/components')
                }
            },
        }
    }
}

Produces: SyntaxError: Named export 'faBars' not found. The requested module '@fortawesome/free-solid-svg-icons' is a CommonJS module, which may not support all module.exports as named exports.

I did see this at the link you provided and I deleted the folder but it did not help: When updating the Svelte compiler options in svelte.config.js or vite.config.js, delete the node_modules/.vite folder to trigger pre-bundling in Vite again.

benmccann commented 2 years ago

It doesn't go under vite. It goes directly in the root like:

const config = {
    experimental: {
        prebundleSvelteLibraries: true
    }
}
BillBuilt commented 2 years ago

hmmm still no change...

/** @type {import('@sveltejs/kit').Config} */
const config = {
    // Consult https://github.com/sveltejs/svelte-preprocess
    // for more information about preprocessors
    preprocess: preprocess(),
    experimental: {
        prebundleSvelteLibraries: true
    },
    kit: {
        adapter: adapter(),
        vite: {
            resolve: {
                alias: {
                    $lib: path.resolve('./src/lib'),
                    $comp: path.resolve('./src/components')
                }
            },
        }
    }
}

produces at build time:

import { faBars, faHome, faInfo, faTools, faEnvelope } from "@fortawesome/free-solid-svg-icons";
         ^^^^^^
SyntaxError: Named export 'faBars' not found. The requested module '@fortawesome/free-solid-svg-icons' is a CommonJS module, which may not support all module.exports as named exports.

whereas this works fine:

/** @type {import('@sveltejs/kit').Config} */
const config = {
    // Consult https://github.com/sveltejs/svelte-preprocess
    // for more information about preprocessors
    preprocess: preprocess(),

    kit: {
        adapter: adapter(),
        vite: {
            resolve: {
                alias: {
                    $lib: path.resolve('./src/lib'),
                    $comp: path.resolve('./src/components')
                }
            },
            ssr: {
                noExternal: ['@fortawesome/free-brands-svg-icons', '@fortawesome/free-regular-svg-icons', '@fortawesome/free-solid-svg-icons']
            },
        }
    }
}

I tried swapping out the adapters and noticed that when using adapter-auto it builds but produces the error upon running npm run preview. When using adapter-node it fails at build time.

benmccann commented 2 years ago

I'm personally using fort-awesome icons without ssr.noExternal or experimental.prebundleSvelteLibraries in one of my projects by using svelte-awesome:

<script>
    import Icon from 'svelte-awesome';
    import { faTwitter } from '@fortawesome/free-brands-svg-icons';
<script>

<Icon data={faTwitter} scale="1.4"/>
BillBuilt commented 2 years ago

I too am using svelte-awesome but for some reason just wants to be finicky!

    import Icon from 'svelte-awesome'
    >>> FAILS: -> import { faBars, faHome, faInfo, faEnvelope, faTools } from '@fortawesome/free-solid-svg-icons'

I'll settle for having to use ssr.noExternal - slightly degraded performance is better than none at all!

benmccann commented 2 years ago

Hmm. That seems quite strange. I wonder if you have an old version of Vite or something. You can run rm -rf node_modules package-lock.json && npm install to update. If that still doesn't fix it, please share a repository that reproduces the issue

BillBuilt commented 2 years ago

Hey @benmccann, Sorry for the delayed response - here is a repo you can use to test. I tried deleting and re-installing but with identical results. I'm sure I'm probably just overlooking something.

src/routes/index.svelte has the imports in it. Thanks

https://github.com/BillBuilt/icontest

Mnigos commented 2 years ago

Just had the same issue and weirdly this solution from layercake issue tracker 👇 worked for me (but with @sanity/client dependency that needs prebundling)

Move vite config to own file vite.config.cjs so that

// vite.config.cjs
const pkg = require('./package.json');

/** @type {import('vite').UserConfig} */
export default {
  ssr: {
    noExternal: Object.keys(pkg.dependencies || {})
  },
};
// svelte.config.cjs
const sveltePreprocess = require('svelte-preprocess');
const node = require('@sveltejs/adapter-node');

/** @type {import('@sveltejs/kit').Config} */
module.exports = {
  preprocess: sveltePreprocess(),
  kit: {
    adapter: node(),
    target: '#svelte',

    // vite: {
    /* moved to vite.config.cjs */
    // }
  }
};

I tried that and still got error ReferenceError: require is not defined in ES module scope, you can use import instead

MrEmanuel commented 2 years ago

I had similar problems as other people here in the thread. My use case it that I'm trying to use @googlemaps/js-api-loader.

I got the same error saying it doesn't export a default. So I did a dynamic import in the onMount lifecycle method. Seems to work both in dev and the package compiles a prod build. I also had to update my config.

    onMount(() => {
        // Import loader on mount, because it doesn't have default export, and svelte doesn't like esm modules
        import('@googlemaps/js-api-loader').then((val) => {
            new val.Loader(loaderOptions).load().then(() => {
                map = new google.maps.Map(document.getElementById('map') as HTMLElement, {
                    center: startPos,
                    zoom: 8,
                    styles: mapStyle
                });
            });
        });
    });
/** @type {import('@sveltejs/kit').Config} */
const config = {
    // Consult https://github.com/sveltejs/svelte-preprocess
    // for more information about preprocessors
    preprocess: preprocess(),

    kit: {
        adapter: adapter({
            pages: 'public',
            assets: 'public',
            fallback: null,
            precompress: false
        }),
        prerender: {
            default: false  // 👈
        }
    }
};
ZodiacWind commented 2 years ago

hi, I used sveletkit and plotly.js-dist-min in my project. yarn dev could work, but yarn build not. The error message is that:

E:\Projects\leakage-detector\node_modules\rollup\dist\shared\rollup.js:19908 var err = new SyntaxError(message); ^

SyntaxError: Unexpected token (37:121525) in E:/Projects/leakage-detector/node_modules/plotly.js-dist-min/plotly.min.js at Parser.pp$4.raise (E:\Projects\leakage-detector\node_modules\rollup\dist\shared\rollup.js:19908:13) at Parser.pp$9.unexpected (E:\Projects\leakage-detector\node_modules\rollup\dist\shared\rollup.js:17202:8) at Parser.pp$5.parseIdent (E:\Projects\leakage-detector\node_modules\rollup\dist\shared\rollup.js:19839:10) at Parser.pp$5.parsePropertyName (E:\Projects\leakage-detector\node_modules\rollup\dist\shared\rollup.js:19643:109) at Parser.pp$5.parseProperty (E:\Projects\leakage-detector\node_modules\rollup\dist\shared\rollup.js:19570:8) at Parser.pp$5.parseObj (E:\Projects\leakage-detector\node_modules\rollup\dist\shared\rollup.js:19524:21) at Parser.pp$5.parseExprAtom (E:\Projects\leakage-detector\node_modules\rollup\dist\shared\rollup.js:19259:17) at Parser.pp$5.parseExprSubscripts (E:\Projects\leakage-detector\node_modules\rollup\dist\shared\rollup.js:19075:19) at Parser.pp$5.parseMaybeUnary (E:\Projects\leakage-detector\node_modules\rollup\dist\shared\rollup.js:19041:17) at Parser.pp$5.parseExprOps (E:\Projects\leakage-detector\node_modules\rollup\dist\shared\rollup.js:18968:19) { pos: 1407827, loc: { column: 121525, file: 'E:/Projects/leakage-detector/node_modules/plotly.js-dist-min/plotly.min.js', line: 37 }, raisedAt: 1407828,

……

id: 'E:/Projects/leakage-detector/node_modules/plotly.js-dist-min/plotly.min.js', hook: 'transform', code: 'PLUGIN_ERROR', plugin: 'commonjs',