XiaoLin1995 / import-meta-loader

The plugin allows you to use vite's `import.meta` syntax with webpack
MIT License
5 stars 1 forks source link

您好,请教下是否支持兼容 JSX 插件? #2

Open dear-lizhihua opened 7 months ago

dear-lizhihua commented 7 months ago

您好,我们在将 Vue CLI 项目改成 Vite 项目,使用了您开发的 import-meta-loader,发现还挺方便的。 后来有人添加了 JSX 插件后,就无法启动。这里我实现一个示例:https://stackblitz.com/edit/vitejs-vite-7ktpnq。 请教下几个问题:

希望您百忙之中可以解答这些提问。祝您身体健康,事业顺利!

yuewuzhijian commented 2 days ago

您好,我们在将 Vue CLI 项目改成 Vite 项目,使用了您开发的 import-meta-loader,发现还挺方便的。 后来有人添加了 JSX 插件后,就无法启动。这里我实现一个示例:https://stackblitz.com/edit/vitejs-vite-7ktpnq。 请教下几个问题:

  • import-meta-loader 能否配置出支持兼容 import-meta-loader
  • 如果不能配置,是否可以支持兼容 JSX 插件

希望您百忙之中可以解答这些提问。祝您身体健康,事业顺利!

我在进行一系列尝试以后,试出来正确配置了,不知道你是不是还需要

dear-lizhihua commented 2 days ago

感谢您的支持和回复。 现在暂时先移除业务开发人员实现的 jsx 代码,以后应该还是会用到的这个 loader 来兼容的。

yuewuzhijian commented 2 days ago

感谢您的支持和回复。 现在暂时先移除业务开发人员实现的 jsx 代码,以后应该还是会用到的这个 loader 来兼容的。

不知道你遇到的问题是什么样的,一般import.meta的语法应该不至于在jsx模版里使用,我个人认为不考虑边界情况,jsx跟js应该没区别,就是配置的问题。 我日常用vue3+ts+少量tsx(组件库的渲染函数),没有出现什么问题。作者给出的配置问题不小,我测试了几十遍以后,基本敲定一套比较合理的配置了,我也做了个包发到npm了,回头做个项目模版。

yuewuzhijian commented 2 days ago

感谢您的支持和回复。 现在暂时先移除业务开发人员实现的 jsx 代码,以后应该还是会用到的这个 loader 来兼容的。

我刚刚试了一下你之前发的示例,这个示例本身就跑不通,缺少babel的配置

XiaoLin1995 commented 2 days ago

支持 jsx 可如下配置:

// vue.config.js
const path = require('node:path');
const { defineConfig } = require('@vue/cli-service');
const importMetaLoader = require('import-meta-loader');

module.exports = defineConfig({
  transpileDependencies: true,
  chainWebpack: (config) => {
    config.module
      .rule('js')
      .test(/\.(js|jsx)$/) // 此处增加 jsx 即可
      .exclude.add(path.resolve('node_modules'))
      .end()
      .use(importMetaLoader)
      .loader('import-meta-loader')
      .options({
        alias: Object.fromEntries(config.resolve.alias.store),
      })
      .end();
  },
});

支持 ts、tsx 可如下配置:

// vue.config.js
const path = require('node:path');
const { defineConfig } = require('@vue/cli-service');
const importMetaLoader = require('import-meta-loader');

module.exports = defineConfig({
  transpileDependencies: true,
  chainWebpack: (config) => {
    config.module
      .rule('ts')
      .test(/\.(ts|tsx)$/) // 修改为 ts、tsx 即可
      .exclude.add(path.resolve('node_modules'))
      .end()
      .use(importMetaLoader)
      .loader('import-meta-loader')
      .options({
        alias: Object.fromEntries(config.resolve.alias.store),
      })
      .end();
  },
});

ts 存在类型报错时,可增加全局类型声明

报错:Property 'glob' does not exist on type 'ImportMeta'.

// vuecli 项目可在 shims-vue.d.ts 中 或 其他全局类型声明文件中,增加如下代码

declare interface ImportMeta extends ImportMeta {
  glob: (url: string | string[], options?: Record<string, any>) => any
}
dear-lizhihua commented 2 hours ago

感谢您百忙之中帮忙解决问题 场景如下:https://stackblitz.com/edit/vitejs-vite-7ktpnq?file=src%2Fcomponents%2Findex.vue,src%2FApp.vue App.vue 加入 import Index from './components/index.vue' 这句就报错。 JSX 引用方式不是通过 .jsx 文件,所以应该不是 loader 那里配置。 JSX 引用方式参考示例里面 ./components/index.vue 文件

<script lang="jsx">
import { ref, unref, defineComponent } from 'vue';
export default defineComponent({
  setup(props, context) {
    const list = ref(['1', '2']);

    const renderItem = (data) => {
      return data.map((item, index) => <div class="search-block">{item}</div>);
    };
    return () => <div>{renderItem(unref(list))}</div>;
  },
});
</script>
XiaoLin1995 commented 2 hours ago

你的示例代码中缺少babel配置, 可以在项目根目录添加 babel.config.js

// babel.config.js
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ]
}

如果需要使用 import.meta.glob,不要忘了 vue.config.js 中也需要增加匹配 jsx

// vue.config.js
const path = require('node:path');
const { defineConfig } = require('@vue/cli-service');
const importMetaLoader = require('import-meta-loader');

module.exports = defineConfig({
  transpileDependencies: true,
  chainWebpack: (config) => {
    config.module
      .rule('js')
      .test(/\.(js|jsx)$/) // 此处需要增加 jsx 
      .exclude.add(path.resolve('node_modules'))
      .end()
      .use(importMetaLoader)
      .loader('import-meta-loader')
      .options({
        alias: Object.fromEntries(config.resolve.alias.store),
      })
      .end();
  },
});