vitepress icon indicating copy to clipboard operation
vitepress copied to clipboard

`vitepress build` fails with `ERR_REQUIRE_ESM`

Open DerYeger opened this issue 2 years ago • 18 comments

Describe the bug

I'm trying to migrate my documentation from a regular Vite setup to Vitepress. Everything works fine when using vitepress dev (except that the CSS is sometimes broken upon first load). However, vitepress build fails with the following output:

$ vitepress build docs
vitepress v0.20.9
✓ building client + server bundles...
- rendering pages...
Error [ERR_REQUIRE_ESM]: require() of ES Module /home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/d3/src/index.js from /home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/vitepress/dist/client/app/temp/demo_index.md.js not supported.
Instead change the require of index.js in /home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/vitepress/dist/client/app/temp/demo_index.md.js to a dynamic import() which is available in all CommonJS modules.
    at Module.<anonymous> (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/vitepress/dist/client/app/temp/demo_index.md.js:25:10)
    at /home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/vitepress/dist/client/app/temp/app.js:1621:12
    at loadPage (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/vitepress/dist/client/app/temp/app.js:163:18)
    at Object.go (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/vitepress/dist/client/app/temp/app.js:156:12)
    at renderPage (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/vitepress/dist/node/serve-61783397.js:40037:10)
    at Object.build (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/vitepress/dist/node/serve-61783397.js:40169:15) {
  code: 'ERR_REQUIRE_ESM'
}
✖ rendering pages...
build error:
 TypeError: Cannot read properties of null (reading 'frontmatter')
    at ReactiveEffect.fn (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/vitepress/dist/client/app/temp/app.js:91:48)
    at ReactiveEffect.run (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/@vue/reactivity/dist/reactivity.cjs.prod.js:153:29)
    at ComputedRefImpl.get value [as value] (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/@vue/reactivity/dist/reactivity.cjs.prod.js:1010:39)
    at ReactiveEffect.fn (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/vitepress/dist/client/app/temp/app.js:1259:23)
    at ReactiveEffect.run (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/@vue/reactivity/dist/reactivity.cjs.prod.js:153:29)
    at ComputedRefImpl.get value [as value] (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/@vue/reactivity/dist/reactivity.cjs.prod.js:1010:39)
    at ReactiveEffect.fn (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/vitepress/dist/client/app/temp/app.js:1279:36)
    at ReactiveEffect.run (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/@vue/reactivity/dist/reactivity.cjs.prod.js:153:29)
    at ComputedRefImpl.get value [as value] (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/@vue/reactivity/dist/reactivity.cjs.prod.js:1010:39)
    at Object.unref (/home/runner/work/d3-graph-controller/d3-graph-controller/node_modules/@vue/reactivity/dist/reactivity.cjs.prod.js:923:29)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Reproduction

  1. Use d3 as a dependency.
  2. Run vitepress build

Expected behavior

The build passes.

System Info

System:
    OS: Windows 10 10.0.22000
    CPU: (24) x64 AMD Ryzen 9 3900X 12-Core Processor            
    Memory: 14.80 GB / 31.92 GB
  Binaries:
    Node: 16.13.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.15 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 7.20.3 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.22000.120.0), Chromium (96.0.1054.62)
    Internet Explorer: 11.0.22000.120
  npmPackages:
    vitepress: 0.20.9 => 0.20.9

Additional context

A reproducing repository is available at https://github.com/DerYeger/d3-graph-controller and a log of the error can be found at https://github.com/DerYeger/d3-graph-controller/runs/4618930216?check_suite_focus=true.

Validations

  • [X] Follow our Code of Conduct
  • [X] Read the docs.
  • [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.

DerYeger avatar Dec 23 '21 14:12 DerYeger

Same thing with my own ESM library. Dev works, but build fails with

 Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/davay/Documents/ФРУКТ/ФРУКТ/frkt.ru/node_modules/.pnpm/@[email protected]/node_modules/@gun-vue/components/dist/index.js from /Users/davay/Documents/ФРУКТ/ФРУКТ/frkt.ru/.vitepress/.temp/app.js not supported.

davay42 avatar Jan 10 '22 15:01 davay42

The library is packaged as ESM only mjs file and vitepress still tries to require() it and fails.

davay42 avatar Jan 10 '22 16:01 davay42

Same error. But vuepress 0.20.10 works

ckvv avatar Jan 12 '22 10:01 ckvv

This is also an issue in vuepress-next https://github.com/vuepress/vuepress-next/issues/617

DerYeger avatar Jan 12 '22 11:01 DerYeger

I opened a PR (#512) to fix this issue, in the meantime this can be fixed by adding a plugin to the Vite configuration:

import { resolve, join } from 'path';
import { writeFileSync } from 'fs';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    {
      name: 'add-common-js-package-plugin',
      writeBundle(options) {
        if (options.format === 'cjs') {
          writeFileSync(
            join(options.dir, 'package.json'), 
            JSON.stringify({ type: 'commonjs' })
          );
        }
      },
    },
  ],
});

Edit: I misread the issue, #512 does not fix this problem, sorry for the confusion.

titouanmathis avatar Jan 31 '22 09:01 titouanmathis

As a workaround, you can use dynamic imports for ESM-only packages. Here is a demo: brc-dd/vitepress-d3-demo.

Arc.vue in the demo is taken from this article (with modifications).

PS: don't do async import at top level of script as it gets interpreted as async vue component and vitepress will try to require() it instead of import()-ing it.

brc-dd avatar Jan 31 '22 11:01 brc-dd

brc-dd/vitepress-d3-demo

Your link top the repo is a 404 for me.

I'd be willing to give it a try and see it if doesn't change the compatibility of the generated modules, but in general I'd prefer to not modify a library for it to be usable in Vitepress/Vuepress. Do you know if this is an inherent issue of the technologies and not solvable in the future?

DerYeger avatar Jan 31 '22 16:01 DerYeger

@DerYeger yeah sorry, forgot to make it public. Check it now.

Do you know if this is an inherent issue of the technologies and not solvable in the future?

It is solvable. I tried working on it but it was taking much time. Someone who has already implemented this in some other framework might be able to fix this proficiently.

in general I'd prefer to not modify a library for it to be usable in Vitepress/Vuepress.

Actually by that workaround you aren't modifying the library, just the way you use it. d3 has got dynamic imports mentioned in their docs too.

brc-dd avatar Jan 31 '22 16:01 brc-dd

@DerYeger yeah sorry, forgot to make it public. Check it now.

Do you know if this is an inherent issue of the technologies and not solvable in the future?

It is solvable. I tried working on it but it was taking much time. Someone who has already implemented this in some other framework might be able to fix this proficiently.

in general I'd prefer to not modify a library for it to be usable in Vitepress/Vuepress.

Actually by that workaround you aren't modifying the library, just the way you use it. d3 has got dynamic imports mentioned in their docs too.

I see, thank you for the example and response! I should have worded it differently, as I meant modifying my own library to use the dynamic imports. d3 is imported in quite a few places there and none of them are async, so I can't really go with that approach. For now, I'll wait until Vitepress/Vuepress-next are compatible with ESM-only packages.

DerYeger avatar Feb 02 '22 16:02 DerYeger

I should have worded it differently, as I meant modifying my own library to use the dynamic imports. d3 is imported in quite a few places there and none of them are async, so I can't really go with that approach.

@DerYeger no, you don't need to change your library. If a user needs to use your library with VitePress, then they need to use dynamic imports. Your library d3-graph-controller works fine with async imports without any changes at your side.

Change Arc.vue in my example to this:

<template>
  <div id="graph" />
</template>

<script setup>
import { onMounted } from 'vue';
import 'd3-graph-controller/default.css';

const generateGraph = async () => {
  const { defineGraph, defineGraphConfig, defineLink, defineNodeWithDefaults, GraphController } =
    await import('d3-graph-controller');
  const a = defineNodeWithDefaults({ type: 'node', id: 'a', label: { color: 'black', fontSize: '1rem', text: 'A' } });
  const b = defineNodeWithDefaults({ type: 'node', id: 'b', label: { color: 'black', fontSize: '1rem', text: 'B' } });
  const link = defineLink({ source: a, target: b, color: 'gray', label: false });
  const graph = defineGraph({ nodes: [a, b], links: [link] });
  const container = document.getElementById('graph');
  const controller = new GraphController(container, graph, defineGraphConfig());
};

onMounted(generateGraph);
</script>

brc-dd avatar Feb 02 '22 19:02 brc-dd

I should have worded it differently, as I meant modifying my own library to use the dynamic imports. d3 is imported in quite a few places there and none of them are async, so I can't really go with that approach.

@DerYeger no, you don't need to change your library. If a user needs to use your library with VitePress, then they need to use dynamic imports. Your library d3-graph-controller works fine with async imports without any changes at your side.

Change Arc.vue in my example to this:

<template>
  <div id="graph" />
</template>

<script setup>
import { onMounted } from 'vue';
import 'd3-graph-controller/default.css';

const generateGraph = async () => {
  const { defineGraph, defineGraphConfig, defineLink, defineNodeWithDefaults, GraphController } =
    await import('d3-graph-controller');
  const a = defineNodeWithDefaults({ type: 'node', id: 'a', label: { color: 'black', fontSize: '1rem', text: 'A' } });
  const b = defineNodeWithDefaults({ type: 'node', id: 'b', label: { color: 'black', fontSize: '1rem', text: 'B' } });
  const link = defineLink({ source: a, target: b, color: 'gray', label: false });
  const graph = defineGraph({ nodes: [a, b], links: [link] });
  const container = document.getElementById('graph');
  const controller = new GraphController(container, graph, defineGraphConfig());
};

onMounted(generateGraph);
</script>

Ahh, thank you! I misunderstood what library had to be imported dynamically. I gave it a try in vuepress-next, but it didn't work and I don't have a Vitepress setup right now. So I'll stay with waiting for future changes.

DerYeger avatar Feb 02 '22 22:02 DerYeger

I'm not sure if the same fix applies to Vitepress, but the approach described in https://github.com/vuepress/vuepress-next/issues/585#issuecomment-1046188074 fixes the issue for Vuepresss 2.

DerYeger avatar Feb 20 '22 08:02 DerYeger

Yeah, setting all the non-ESM-ready packages as ssr: { noExternal: ['package-one', 'package-two'] } fixes the problem! Recent vitepress builds everything just fine! 🔥

davay42 avatar Feb 20 '22 13:02 davay42

@davay42 where should I add that code? image

mesqueeb avatar Jun 14 '22 03:06 mesqueeb

@mesqueeb create a vite.config.js near your package.json and paste it there:

import { defineConfig } from 'vite'
export default defineConfig({
  ssr: {
    noExternal: ['lib-1', 'lib-2']
  },
})

davay42 avatar Jun 14 '22 08:06 davay42

@mesqueeb create a vite.config.js near your package.json and paste it there:

import { defineConfig } from 'vite'
export default defineConfig({
  ssr: {
    noExternal: ['lib-1', 'lib-2']
  },
})

I use this cofnig fixed! but has another quesition when render pages : (

image

JobinJia avatar Jun 15 '22 05:06 JobinJia

@JobinJia Its happening because you're using some non SSR compatible library or code.

brc-dd avatar Jun 15 '22 06:06 brc-dd

Oh, tks But how should i can find that non SSR library? An can't find some message in build logs : (

JobinJia avatar Jun 15 '22 06:06 JobinJia