⚠
vite-plugin-ssr has been renamed Vike, see migration guide.

Broken npm package

Some npm packages contain code that isn't valid JavaScript, which makes Node.js crash.

Solution

The workaround is to add npm packages containing invalid code to vite.config.js > ssr.noExternal.

// vite.config.js

export default {
  ssr: {
    // Add npm packages containing invalid code here
    noExternal: ['some-library']
  }
}

The reason why many npm packages contain erroneous code is because frameworks like Next.js transpile the server-side code of npm packages. (Whereas Vite lets Node.js directly execute npm packages in order to improve DX speed: Vite transpiles only what is strictly needed). Where Next.js is permissive and is able to process invalid code, Node.js is strict and crashes upon invalid code. By adding npm packages to vite.config.js > ssr.noExternal we replicate the behavior of frameworks like Next.js.

Errors

List of known errors that Node.js throws when it tries to execute the invalid code of some library.

The most notable issues are invalid ESM and invalid CSS imports, see errors and solution.

Cannot use import statement outside a module

SyntaxError: Cannot use import statement outside a module
(node:30335) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
node_modules/some-library/dist/esm/index.js:1
SyntaxError: Cannot use import statement outside a module
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1033:15)
    at Module._compile (node:internal/modules/cjs/loader:1069:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Module._load (node:internal/modules/cjs/loader:827:12)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:170:29)
    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:409:24)

Node.js v18.0.0

Node.js's message set "type": "module" in package.json or use the .mjs extension is misleading because it means the library's node_modules/some-library/package.json, not our package.json. It's not really actionable (unless we patch the library, e.g. with pnpm.packageExtensions or pnpm patch).

Named export not found

import { SomeImport } from "some-library";
         ^^^^^^^^^^
SyntaxError: Named export 'SomeImport' not found. The requested module 'some-library' 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 'some-library';
const { SomeImport } = pkg;

    at ModuleJob._instantiate (node:internal/modules/esm/module_job:124:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:190:5)

Node.js v18.0.0

The workaround proposed by Node.js often doesn't work for default exports. If it doesn't, try this instead:

- import theDefaultExport from 'some-library'
+ import lib from 'some-library';
+ const theDefaultExport = lib.default ?? lib

Alternatives:

ERR_MODULE_NOT_FOUND

node:internal/process/esm_loader:91
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'node_modules/some-library/dist/esm/some-file' imported from node_modules/some-library/dist/esm/index.js
Did you mean to import some-file.js?
    at new NodeError (node:internal/errors:372:5)
    at finalizeResolution (node:internal/modules/esm/resolve:405:11)
    at moduleResolve (node:internal/modules/esm/resolve:966:10)
    at defaultResolve (node:internal/modules/esm/resolve:1176:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:605:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:318:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:80:40)
    at link (node:internal/modules/esm/module_job:78:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Node.js v18.0.0

The error is usually thrown when the library's ESM code contains import './some-file'. (It should be import './some-file.js' instead, as imports in ESM code are required to include the file extension.)

ERR_UNSUPPORTED_DIR_IMPORT

Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import 'node_modules/some-library/dist/some-dir/' is not supported resolving ES modules imported from node_modules/some-library/dist/index.js
Did you mean to import ./some-dir/index.js?
    at finalizeResolution (node:internal/modules/esm/resolve:412:17)

ESM doesn't allow directory imports: all import paths need to point to a filename instead.

ERR_UNKNOWN_FILE_EXTENSION .css

Another common problem is code importing CSS which makes Node.js crash:

Error: ERR_UNKNOWN_FILE_EXTENSION .css node_modules/some-library/dist/main.css
    at someFunction (node_modules/some-library/dist/main.js)
    at nextLoad (node:internal/modules/esm/loader:163:28)
    at ESMLoader.load (node:internal/modules/esm/loader:605:26)