evanw / esbuild

An extremely fast bundler for the web
https://esbuild.github.io/
MIT License
38.22k stars 1.16k forks source link

How to enable jsx syntax extension~ #3925

Closed Lisheri closed 2 months ago

Lisheri commented 2 months ago

Problem description

When I add the jsx configuration to the loader according to the documentation, I still get an error when building the vue component library.

image

My configuration

My esbuild core configuration is as follows:

async function buildLibrary() {
  await build({
    entryPoints: ['./src/*.ts'],
    outdir: 'es',
    bundle: true,
    format: 'esm',
    tsconfig: 'tsconfig.json',
    // treeShaking: true,
    // minify: true,
    external: ['vue', 'ant-design-vue'],
    loader: {
      '.eot': 'file',
      '.svg': 'file',
      '.ttf': 'file',
      '.woff': 'file',
      '.png': 'file',
      '.jpg': 'file',
      '.jpeg': 'file',
      '.gif': 'file',
      '.js': 'jsx'
    },
    jsxFactory: 'h',
    jsxFragment: 'Fragment',
    define: {
      __DEV__: 'true'
    },
    inject: ['./script/jsxFactory.js'],
    plugins: [
      alias({
        '@': getReflectPath()
      }),
      vueMacros({
        vue: vuePlugin(),
        vueJsx: VueJsx()
      }),
      sassPlugin({
        sourceMap: true,
        sassOptions: {
          outputStyle: 'compressed',
          sourceMap: true
        }
      }),
      progress(),
      buildTimePlugin(new Date().valueOf())
    ]
  });
}

demo code repository

https://github.com/Lisheri/esbuild_v3_component/tree/main

hyrious commented 2 months ago

The Vue template syntax is NOT JSX. You need to use the Vue compiler to compile the code to valid JavaScript. A quick search about existing plugin: https://github.com/pipe01/esbuild-plugin-vue3

Lisheri commented 2 months ago

The Vue template syntax is NOT JSX. You need to use the Vue compiler to compile the code to valid JavaScript. A quick search about existing plugin: https://github.com/pipe01/esbuild-plugin-vue3

But I've added unplugin-vue to handle sfc~

hyrious commented 2 months ago

This is an issue with unplugin-vue-macros which failed to process the Vue file using unplugin-vue, not with esbuild. For reference:

  1. Only using unplugin-vue is fine in a smoking test case.
  2. It fails with the plugin VueMacros({ plugins: { vue: Vue() } }).
  3. unplugin-vue-macros uses createCombinePlugin() from unplugin-combine, which simply runs each unplugin's setup() on one build.
  4. To mimic a rollup-like plugin API in esbuild, unplugin hacks the build object to provide an onTransform hook, meaning that each plugin instance from vue macros are calling build.onLoad({ filter: /.*/ }).
  5. Let's look at 4 more carefully, it says that if some onTransform() hook returns contents, it will be returned to esbuild's onLoad(). If all transforms are done in a single plugin, then the logic is ok. However there're actually multiple plugin instances registering the transform hook (3). So once some plugin's transform returns code, the other plugins' transform hook will not be called.
  6. In this issue it is unplugin-vue-hoist-static blocks unplugin-vue.

In summary, the transform hook mimiced by unplugin is problematic when there're multiple transform hooks from different plugin instances registered on the same file. It is still possible to fix from unplugin-combine with a bit of tricky. @sxzz

evanw commented 2 months ago

I'm closing this issue because esbuild intentionally doesn't support Vue syntax (only JSX). If you want to support Vue syntax then you'll have to use a Vue plugin, and if you're having problems with that plugin then you'll have to work that out with the plugin author. Vue syntax is outside of esbuild's scope.

sxzz commented 2 months ago

The core reason is not JSX, but that esbuild does not support transforming code again within each plugin like rollup does (of course, this is not an issue with esbuild). In unplugin, we can only hack and simulate this behavior.

We will discuss the issue in https://github.com/vue-macros/vue-macros/issues/824