martonlederer / esbuild-plugin-postcss2

Use postcss with esbuild
MIT License
33 stars 19 forks source link

Can't compile bulma css #27

Open baurine opened 2 years ago

baurine commented 2 years ago

What I did

  1. Init an near-empty react project from template: https://github.com/baurine/esbuild-react-app-ts-template/tree/refine_builder

    Currently, it has only esbuild self, no any plugins.

  2. Install bulma-css by following https://www.npmjs.com/package/bulma

    $ yarn add bulma
  3. import "bulma/css/bulma.css" in src/App.tsx or @import "bulma/css/bulma.css"; in src/style.css, both work fine, esbuild can compile CSS by itself.

    // src/App.tsx
    import "bulma/css/bulma.css"

    Or

    /* src/style.css */
    @import "bulma/css/bulma.css";

    Demo code: https://github.com/miscs-test/esbuild-demo/commit/fce2e09fccf18cc940f1ffea4f5605ab3ec093a8

  4. Install esbuild-plugin-postcss2 to handle CSS files.

    $ yarn add esbuild-plugin-postcss2 -D

    If I import bulma.css in the App.tsx, running yarn build reports following errors:

    $ NODE_ENV=production node builder.js
    > src/App.tsx:6:7: error: [plugin: postcss2] ENOENT: no such file or directory, open '/mnt/bao/codes/personal/try-esbuild/esbuild-demo/src/bulma/css/bulma.css'
        6 │ import 'bulma/css/bulma.css'
          ╵        ~~~~~~~~~~~~~~~~~~~~~
      node_modules/esbuild-plugin-postcss2/dist/index.js:65:10: note: This error came from the "onResolve" callback registered here
        65 │     build.onResolve({filter: /.\.(css|sass|scss|less|styl)$/}, async (args) => {
          ╵           ~~~~~~~~~
        at setup (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild-plugin-postcss2/dist/index.js:65:11)
        at handlePlugins (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:741:23)
        at Object.buildOrServe (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1029:7)
        at /mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1804:17
        at new Promise (<anonymous>)
        at Object.build (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1803:14)
        at build (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1658:51)
        at /mnt/bao/codes/personal/try-esbuild/esbuild-demo/builder.js:47:25
        at Object.<anonymous> (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/builder.js:58:3)
    
    /mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1478
      let error = new Error(`${text}${summary}`);
                  ^
    
    Error: Build failed with 1 error:
    src/App.tsx:6:7: error: [plugin: postcss2] ENOENT: no such file or directory, open '/mnt/bao/codes/personal/try-esbuild/esbuild-demo/src/bulma/css/bulma.css'
        at failureErrorWithLog (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1478:15)
        at /mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1136:28
        at runOnEndCallbacks (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:926:63)
        at buildResponseToResult (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1134:7)
        at /mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1243:14
        at /mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:614:9
        at handleIncomingPacket (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:711:9)
        at Socket.readFromStdout (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:581:7)
        at Socket.emit (node:events:390:28)
        at addChunk (node:internal/streams/readable:315:12) {
      errors: [
        {
          detail: [Error: ENOENT: no such file or directory, open '/mnt/bao/codes/personal/try-esbuild/esbuild-demo/src/bulma/css/bulma.css'] {
            errno: -2,
            code: 'ENOENT',
            syscall: 'open',
            path: '/mnt/bao/codes/personal/try-esbuild/esbuild-demo/src/bulma/css/bulma.css'
          },
          location: {
            column: 7,
            file: 'src/App.tsx',
            length: 21,
            line: 6,
            lineText: "import 'bulma/css/bulma.css'",
            namespace: '',
            suggestion: ''
          },
          notes: [
            {
              location: {
                column: 10,
                file: 'node_modules/esbuild-plugin-postcss2/dist/index.js',
                length: 9,
                line: 65,
                lineText: '    build.onResolve({filter: /.\\.(css|sass|scss|less|styl)$/}, async (args) => {\n' +
                  '    at setup (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild-plugin-postcss2/dist/index.js:65:11)\n' +
                  '    at handlePlugins (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:741:23)\n' +
                  '    at Object.buildOrServe (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1029:7)\n' +
                  '    at /mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1804:17\n' +
                  '    at new Promise (<anonymous>)\n' +
                  '    at Object.build (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1803:14)\n' +
                  '    at build (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1658:51)\n' +
                  '    at /mnt/bao/codes/personal/try-esbuild/esbuild-demo/builder.js:47:25\n' +
                  '    at Object.<anonymous> (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/builder.js:58:3)',
                namespace: 'file',
                suggestion: ''
              },
              text: 'This error came from the "onResolve" callback registered here'
            }
          ],
          pluginName: 'postcss2',
          text: "ENOENT: no such file or directory, open '/mnt/bao/codes/personal/try-esbuild/esbuild-demo/src/bulma/css/bulma.css'"
        }
      ],
      warnings: []
    }
    error Command failed with exit code 1.

    If I import the bulma.css in the style.css, it reports the following errors:

    $ NODE_ENV=production node builder.js
    > ../../../../../../tmp/tmp-1718725-2Ubh7VAjfN1Z/17d800fd6570/style.css:3:8: error: [plugin: postcss2] ENOENT: no such file or directory, open '/tmp/tmp-1718725-2Ubh7VAjfN1Z/17d800fd6570/bulma/css/bulma.css'
        3 │ @import 'bulma/css/bulma.css';
          ╵         ~~~~~~~~~~~~~~~~~~~~~
      node_modules/esbuild-plugin-postcss2/dist/index.js:65:10: note: This error came from the "onResolve" callback registered here
        65 │     build.onResolve({filter: /.\.(css|sass|scss|less|styl)$/}, async (args) => {
          ╵           ~~~~~~~~~
        at setup (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild-plugin-postcss2/dist/index.js:65:11)
        at handlePlugins (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:741:23)
        at Object.buildOrServe (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1029:7)
        at /mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1804:17
        at new Promise (<anonymous>)
        at Object.build (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1803:14)
        at build (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1658:51)
        at /mnt/bao/codes/personal/try-esbuild/esbuild-demo/builder.js:47:25
        at Object.<anonymous> (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/builder.js:58:3)
    
    /mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1478
      let error = new Error(`${text}${summary}`);
                  ^
    
    Error: Build failed with 1 error:
    ../../../../../../tmp/tmp-1718725-2Ubh7VAjfN1Z/17d800fd6570/style.css:3:8: error: [plugin: postcss2] ENOENT: no such file or directory, open '/tmp/tmp-1718725-2Ubh7VAjfN1Z/17d800fd6570/bulma/css/bulma.css'
        at failureErrorWithLog (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1478:15)
        at /mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1136:28
        at runOnEndCallbacks (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:926:63)
        at buildResponseToResult (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1134:7)
        at /mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1243:14
        at /mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:614:9
        at handleIncomingPacket (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:711:9)
        at Socket.readFromStdout (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:581:7)
        at Socket.emit (node:events:390:28)
        at addChunk (node:internal/streams/readable:315:12) {
      errors: [
        {
          detail: [Error: ENOENT: no such file or directory, open '/tmp/tmp-1718725-2Ubh7VAjfN1Z/17d800fd6570/bulma/css/bulma.css'] {
            errno: -2,
            code: 'ENOENT',
            syscall: 'open',
            path: '/tmp/tmp-1718725-2Ubh7VAjfN1Z/17d800fd6570/bulma/css/bulma.css'
          },
          location: {
            column: 8,
            file: '../../../../../../tmp/tmp-1718725-2Ubh7VAjfN1Z/17d800fd6570/style.css',
            length: 21,
            line: 3,
            lineText: "@import 'bulma/css/bulma.css';",
            namespace: '',
            suggestion: ''
          },
          notes: [
            {
              location: {
                column: 10,
                file: 'node_modules/esbuild-plugin-postcss2/dist/index.js',
                length: 9,
                line: 65,
                lineText: '    build.onResolve({filter: /.\\.(css|sass|scss|less|styl)$/}, async (args) => {\n' +
                  '    at setup (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild-plugin-postcss2/dist/index.js:65:11)\n' +
                  '    at handlePlugins (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:741:23)\n' +
                  '    at Object.buildOrServe (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1029:7)\n' +
                  '    at /mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1804:17\n' +
                  '    at new Promise (<anonymous>)\n' +
                  '    at Object.build (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1803:14)\n' +
                  '    at build (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/node_modules/esbuild/lib/main.js:1658:51)\n' +
                  '    at /mnt/bao/codes/personal/try-esbuild/esbuild-demo/builder.js:47:25\n' +
                  '    at Object.<anonymous> (/mnt/bao/codes/personal/try-esbuild/esbuild-demo/builder.js:58:3)',
                namespace: 'file',
                suggestion: ''
              },
              text: 'This error came from the "onResolve" callback registered here'
            }
          ],
          pluginName: 'postcss2',
          text: "ENOENT: no such file or directory, open '/tmp/tmp-1718725-2Ubh7VAjfN1Z/17d800fd6570/bulma/css/bulma.css'"
        }
      ],
      warnings: []
    }
    error Command failed with exit code 1.

    Demo code: https://github.com/miscs-test/esbuild-demo/commit/3c7dac6a6247c94fc7bde05f53178756f0f25367

I found the reason is that the below line code doesn't work as expect:

https://github.com/martonlederer/esbuild-plugin-postcss2/blob/b631aa4ea40b665383cc637ce0e75f5a1e7f1db7/src/index.ts?_pjax=%23js-repo-pjax-container%2C%20div%5Bitemtype%3D%22http%3A%2F%2Fschema.org%2FSoftwareSourceCode%22%5D%20main%2C%20%5Bdata-pjax-container%5D#L88

        let sourceFullPath = resolveFile(args.path);

When args.path is bulma/css/bulma.css, it returns null.

I also report the issue to resolve-file lib: https://github.com/doowb/resolve-file/issues/2#issuecomment-985319132

Workarounds

I can workaround this bug by following 3 methods:

  1. hack the node_modules/resolve-file/index.js, modify the following code:

      if (!utils.exists(file.path)) {
        try {
          if (/[\\\/]/.test(name)) {
            file.basename = path.basename(name);
            var dirname = path.dirname(name);
            file.name = path.basename(dirname);
    -       file.main = require.resolve(dirname);
    +       // file.main = require.resolve(dirname);
    +       file.main = require.resolve(name);
            file.path = path.resolve(path.dirname(file.main), file.basename);
          }
  2. hack the node_modules/esbuild-plugin-postcss2/dist/index.js, remove the css| from the onResolve filters, so esbuild-plugin-postcss2 won't parse the css, and esbuild self will parse it.

  3. hack the node_modules/esbuild-plugin-postcss2/dist/index.js, add following logic:

    // hack
    let exist = await import_fs_extra.exists(sourceFullPath)
    if (!exist) {
      sourceFullPath = import_path.default.resolve(
        process.cwd(),
        'node_modules',
        args.path
      )
    }