vuejs / vitepress

Vite & Vue powered static site generator.
https://vitepress.dev
MIT License
11.48k stars 1.86k forks source link

`vitepress build` fails with `ERR_REQUIRE_ESM` #476

Closed DerYeger closed 1 year ago

DerYeger commented 2 years ago

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

davay42 commented 2 years ago

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/@gun-vue+components@0.3.1/node_modules/@gun-vue/components/dist/index.js from /Users/davay/Documents/ФРУКТ/ФРУКТ/frkt.ru/.vitepress/.temp/app.js not supported.
davay42 commented 2 years ago

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

ckvv commented 2 years ago

Same error. But vuepress 0.20.10 works

DerYeger commented 2 years ago

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

titouanmathis commented 2 years ago

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.

brc-dd commented 2 years ago

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.

DerYeger commented 2 years ago

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?

brc-dd commented 2 years ago

@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.

DerYeger commented 2 years ago

@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.

brc-dd commented 2 years ago

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>
DerYeger commented 2 years ago

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 commented 2 years ago

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.

davay42 commented 2 years ago

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

mesqueeb commented 1 year ago

@davay42 where should I add that code?

image
davay42 commented 1 year ago

@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']
  },
})
JobinJia commented 1 year ago

@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
brc-dd commented 1 year ago

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

JobinJia commented 1 year ago

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