@esmx/rspack-vue 3.0.0-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +2 -0
- package/dist/vue-core.d.ts +5 -0
- package/dist/vue-core.mjs +91 -0
- package/dist/vue.d.ts +61 -0
- package/dist/vue.mjs +7 -0
- package/dist/vue2-loader.d.ts +3 -0
- package/dist/vue2-loader.mjs +22 -0
- package/dist/vue3-loader.d.ts +3 -0
- package/dist/vue3-loader.mjs +19 -0
- package/package.json +91 -0
- package/src/index.ts +2 -0
- package/src/vue-core.ts +110 -0
- package/src/vue.ts +69 -0
- package/src/vue2-loader.ts +28 -0
- package/src/vue3-loader.ts +24 -0
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# @esmx/rspack-vue
|
|
2
|
+
|
|
3
|
+
为 Vue 框架提供专业的构建支持,包含完整的 Vue 组件开发、构建与服务端渲染能力。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- 🚀 **高性能构建** - 基于 Rspack 的高性能构建,为 Vue 应用提供极致开发体验
|
|
8
|
+
- 💡 **框架集成** - 完整支持 Vue 2/3,内置 vue-loader 及相关优化配置
|
|
9
|
+
- 🎨 **组件支持** - 智能处理 .vue 单文件组件,支持模板、样式和脚本
|
|
10
|
+
- 🛠️ **SSR 支持** - 内置服务端渲染支持,轻松构建同构应用
|
|
11
|
+
- 🔧 **开发体验** - 支持热更新、智能提示和 TypeScript
|
|
12
|
+
|
|
13
|
+
## 安装
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm add @esmx/rspack-vue -D
|
|
17
|
+
# 或
|
|
18
|
+
yarn add @esmx/rspack-vue -D
|
|
19
|
+
# 或
|
|
20
|
+
npm install @esmx/rspack-vue -D
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 文档
|
|
24
|
+
|
|
25
|
+
访问 [@esmx/rspack-vue 官方文档](https://www.esmnext.com/api/app/rspack-vue.html) 获取详细的使用指南和 API 文档。
|
|
26
|
+
|
|
27
|
+
## 许可证
|
|
28
|
+
|
|
29
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Esmx } from '@esmx/core';
|
|
2
|
+
import type { RspackVueAppOptions } from './vue';
|
|
3
|
+
type VueType = '2' | '3';
|
|
4
|
+
export declare function createRspackVueApp(esmx: Esmx, vueType: VueType, options?: RspackVueAppOptions): Promise<import("@esmx/core").App>;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { createRspackHtmlApp, rspack } from "@esmx/rspack";
|
|
2
|
+
import { VueLoaderPlugin as VueLoader2Plugin } from "vue2-loader";
|
|
3
|
+
import { VueLoaderPlugin as VueLoader3Plugin } from "vue3-loader";
|
|
4
|
+
import { vue2Loader } from "./vue2-loader.mjs";
|
|
5
|
+
import { vue3Loader } from "./vue3-loader.mjs";
|
|
6
|
+
export function createRspackVueApp(esmx, vueType, options) {
|
|
7
|
+
return createRspackHtmlApp(esmx, {
|
|
8
|
+
...options,
|
|
9
|
+
loaders: {
|
|
10
|
+
styleLoader: new URL(import.meta.resolve("vue-style-loader")).pathname,
|
|
11
|
+
...options?.loaders
|
|
12
|
+
},
|
|
13
|
+
config(context) {
|
|
14
|
+
const { config, buildTarget } = context;
|
|
15
|
+
config.resolve = {
|
|
16
|
+
...config.resolve,
|
|
17
|
+
extensions: [...config.resolve?.extensions ?? [], ".vue"]
|
|
18
|
+
};
|
|
19
|
+
config.plugins = config.plugins || [];
|
|
20
|
+
switch (vueType) {
|
|
21
|
+
case "2":
|
|
22
|
+
config.plugins.push(new VueLoader2Plugin());
|
|
23
|
+
break;
|
|
24
|
+
case "3":
|
|
25
|
+
config.plugins.push(new VueLoader3Plugin());
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
if (buildTarget === "client") {
|
|
29
|
+
config.plugins.push(
|
|
30
|
+
new rspack.DefinePlugin({
|
|
31
|
+
"process.env.VUE_ENV": JSON.stringify(buildTarget)
|
|
32
|
+
})
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
const vueRuleUse = [
|
|
36
|
+
{
|
|
37
|
+
loader: new URL(import.meta.resolve(`vue${vueType}-loader`)).pathname,
|
|
38
|
+
options: {
|
|
39
|
+
...options?.vueLoader,
|
|
40
|
+
experimentalInlineMatchResource: true,
|
|
41
|
+
optimizeSSR: buildTarget === "server"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
];
|
|
45
|
+
switch (vueType) {
|
|
46
|
+
case "2":
|
|
47
|
+
vueRuleUse.unshift(vue2Loader);
|
|
48
|
+
break;
|
|
49
|
+
case "3":
|
|
50
|
+
vueRuleUse.unshift(vue3Loader);
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
config.module = {
|
|
54
|
+
...config.module,
|
|
55
|
+
rules: [
|
|
56
|
+
...config.module?.rules ?? [],
|
|
57
|
+
{
|
|
58
|
+
test: /\.vue$/,
|
|
59
|
+
use: vueRuleUse
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
};
|
|
63
|
+
let vueAlias = null;
|
|
64
|
+
switch (vueType) {
|
|
65
|
+
case "2":
|
|
66
|
+
vueAlias = "vue/dist/vue.esm.js";
|
|
67
|
+
break;
|
|
68
|
+
case "3":
|
|
69
|
+
vueAlias = "vue/dist/vue.runtime.esm-browser.js";
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
if (vueAlias) {
|
|
73
|
+
config.resolve.alias = {
|
|
74
|
+
...config.resolve.alias,
|
|
75
|
+
vue$: vueAlias
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (vueType === "2") {
|
|
79
|
+
config.ignoreWarnings = [
|
|
80
|
+
...config.ignoreWarnings ?? [],
|
|
81
|
+
(warning) => {
|
|
82
|
+
return warning.moduleDescriptor.name.includes(
|
|
83
|
+
"vue-server-renderer"
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
];
|
|
87
|
+
}
|
|
88
|
+
options?.config?.(context);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
package/dist/vue.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { Esmx } from '@esmx/core';
|
|
2
|
+
import type { RspackHtmlAppOptions } from '@esmx/rspack';
|
|
3
|
+
export interface RspackVueAppOptions extends RspackHtmlAppOptions {
|
|
4
|
+
/**
|
|
5
|
+
* vue-loader 配置项
|
|
6
|
+
*
|
|
7
|
+
* 用于配置 Vue 单文件组件的编译选项,完整选项参考:
|
|
8
|
+
* https://github.com/vuejs/vue-loader
|
|
9
|
+
*/
|
|
10
|
+
vueLoader?: Record<string, any>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 创建 Vue 2 应用构建器
|
|
14
|
+
*
|
|
15
|
+
* @param esmx - Esmx 实例
|
|
16
|
+
* @param options - Rspack Vue 应用配置项
|
|
17
|
+
* @returns 返回一个 Promise,解析为构建好的应用实例
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* import type { EsmxOptions } from '@esmx/core';
|
|
22
|
+
*
|
|
23
|
+
* export default {
|
|
24
|
+
* async devApp(esmx) {
|
|
25
|
+
* return import('@esmx/rspack-vue').then((m) =>
|
|
26
|
+
* m.createRspackVue2App(esmx, {
|
|
27
|
+
* config({ config }) {
|
|
28
|
+
* // 自定义 Rspack 配置
|
|
29
|
+
* }
|
|
30
|
+
* })
|
|
31
|
+
* );
|
|
32
|
+
* }
|
|
33
|
+
* } satisfies EsmxOptions;
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function createRspackVue2App(esmx: Esmx, options?: RspackVueAppOptions): Promise<import("@esmx/core").App>;
|
|
37
|
+
/**
|
|
38
|
+
* 创建 Vue 3 应用构建器
|
|
39
|
+
*
|
|
40
|
+
* @param esmx - Esmx 实例
|
|
41
|
+
* @param options - Rspack Vue 应用配置项
|
|
42
|
+
* @returns 返回一个 Promise,解析为构建好的应用实例
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import type { EsmxOptions } from '@esmx/core';
|
|
47
|
+
*
|
|
48
|
+
* export default {
|
|
49
|
+
* async devApp(esmx) {
|
|
50
|
+
* return import('@esmx/rspack-vue').then((m) =>
|
|
51
|
+
* m.createRspackVue3App(esmx, {
|
|
52
|
+
* config({ config }) {
|
|
53
|
+
* // 自定义 Rspack 配置
|
|
54
|
+
* }
|
|
55
|
+
* })
|
|
56
|
+
* );
|
|
57
|
+
* }
|
|
58
|
+
* } satisfies EsmxOptions;
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare function createRspackVue3App(esmx: Esmx, options?: RspackVueAppOptions): Promise<import("@esmx/core").App>;
|
package/dist/vue.mjs
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createRspackVueApp } from "./vue-core.mjs";
|
|
2
|
+
export function createRspackVue2App(esmx, options) {
|
|
3
|
+
return createRspackVueApp(esmx, "2", options);
|
|
4
|
+
}
|
|
5
|
+
export function createRspackVue3App(esmx, options) {
|
|
6
|
+
return createRspackVueApp(esmx, "3", options);
|
|
7
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const FIX_ESM = `api.install(require('vue').default)`;
|
|
2
|
+
const ADD_IMPORT = `
|
|
3
|
+
function initImport () {
|
|
4
|
+
const mixins = Array.isArray(component.options.mixins) ? component.options.mixins : [];
|
|
5
|
+
mixins.push({
|
|
6
|
+
serverPrefetch () {
|
|
7
|
+
this.$ssrContext?.importMetaSet?.add(import.meta);
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
component.options.mixins = mixins;
|
|
11
|
+
}
|
|
12
|
+
initImport();
|
|
13
|
+
export default component.exports
|
|
14
|
+
`;
|
|
15
|
+
export default function(text) {
|
|
16
|
+
text = text.replaceAll(`api.install(require('vue'))`, FIX_ESM);
|
|
17
|
+
if (typeof this.target === "string" && this.target.includes("node")) {
|
|
18
|
+
text = text.replaceAll("export default component.exports", ADD_IMPORT);
|
|
19
|
+
}
|
|
20
|
+
return text;
|
|
21
|
+
}
|
|
22
|
+
export const vue2Loader = new URL(import.meta.resolve(import.meta.url)).pathname;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const ADD_IMPORT = `
|
|
2
|
+
import { useSSRContext } from 'vue';
|
|
3
|
+
function initImport () {
|
|
4
|
+
|
|
5
|
+
const mixins = Array.isArray(__exports__.mixins) ? __exports__.mixins : [];
|
|
6
|
+
mixins.push({
|
|
7
|
+
created () {
|
|
8
|
+
const ctx = useSSRContext();
|
|
9
|
+
ctx?.importMetaSet?.add(import.meta);
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
__exports__.mixins = mixins;
|
|
13
|
+
}
|
|
14
|
+
initImport();
|
|
15
|
+
`;
|
|
16
|
+
export default function(text) {
|
|
17
|
+
return text + ADD_IMPORT;
|
|
18
|
+
}
|
|
19
|
+
export const vue3Loader = new URL(import.meta.resolve(import.meta.url)).pathname;
|
package/package.json
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@esmx/rspack-vue",
|
|
3
|
+
"description": "A high-performance Vue integration for Esmx microfrontend framework, providing Vue 2/3 support with SSR and Module Federation capabilities.",
|
|
4
|
+
"author": {
|
|
5
|
+
"name": "lzxb",
|
|
6
|
+
"url": "https://github.com/lzxb"
|
|
7
|
+
},
|
|
8
|
+
"contributors": [
|
|
9
|
+
{
|
|
10
|
+
"name": "RockShi1994",
|
|
11
|
+
"url": "https://github.com/RockShi1994"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "jerrychan7",
|
|
15
|
+
"url": "https://github.com/jerrychan7"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/js-esm/esmx.git",
|
|
21
|
+
"directory": "packages/rspack-vue"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://github.com/js-esm/esmx",
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/js-esm/esmx/issues"
|
|
26
|
+
},
|
|
27
|
+
"template": "library-node",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"keywords": [
|
|
30
|
+
"Vue",
|
|
31
|
+
"Vue 2",
|
|
32
|
+
"Vue 3",
|
|
33
|
+
"Rspack",
|
|
34
|
+
"SSR",
|
|
35
|
+
"Module Federation",
|
|
36
|
+
"High Performance",
|
|
37
|
+
"Build Tool",
|
|
38
|
+
"Development Experience",
|
|
39
|
+
"Hot Module Replacement",
|
|
40
|
+
"TypeScript"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"lint:js": "biome check --write --no-errors-on-unmatched",
|
|
44
|
+
"lint:css": "stylelint '**/*.{css,vue}' --fix --aei",
|
|
45
|
+
"lint:type": "tsc --noEmit",
|
|
46
|
+
"test": "vitest run --pass-with-no-tests",
|
|
47
|
+
"coverage": "vitest run --coverage --pass-with-no-tests",
|
|
48
|
+
"build": "unbuild"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"@esmx/core": "*",
|
|
52
|
+
"vue": ">=2.7.8 || >=3.0.0"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@esmx/rspack": "3.0.0-rc.10",
|
|
56
|
+
"vue-style-loader": "^4.1.3",
|
|
57
|
+
"vue2-loader": "npm:vue-loader@15.11.1",
|
|
58
|
+
"vue3-loader": "npm:vue-loader@^17.4.2"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@biomejs/biome": "1.9.4",
|
|
62
|
+
"@esmx/core": "3.0.0-rc.10",
|
|
63
|
+
"@esmx/lint": "3.0.0-rc.10",
|
|
64
|
+
"@types/node": "22.13.10",
|
|
65
|
+
"@vitest/coverage-v8": "3.0.8",
|
|
66
|
+
"stylelint": "16.15.0",
|
|
67
|
+
"typescript": "5.8.2",
|
|
68
|
+
"unbuild": "2.0.0",
|
|
69
|
+
"vitest": "3.0.8"
|
|
70
|
+
},
|
|
71
|
+
"version": "3.0.0-rc.10",
|
|
72
|
+
"type": "module",
|
|
73
|
+
"private": false,
|
|
74
|
+
"exports": {
|
|
75
|
+
".": {
|
|
76
|
+
"import": "./dist/index.mjs",
|
|
77
|
+
"types": "./dist/index.d.ts"
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"module": "dist/index.mjs",
|
|
81
|
+
"types": "./dist/index.d.ts",
|
|
82
|
+
"files": [
|
|
83
|
+
"lib",
|
|
84
|
+
"src",
|
|
85
|
+
"dist",
|
|
86
|
+
"*.mjs",
|
|
87
|
+
"template",
|
|
88
|
+
"public"
|
|
89
|
+
],
|
|
90
|
+
"gitHead": "4a528ffecfdc6f2c6e7d97bc952427745f467691"
|
|
91
|
+
}
|
package/src/index.ts
ADDED
package/src/vue-core.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { Esmx } from '@esmx/core';
|
|
2
|
+
import { createRspackHtmlApp, rspack } from '@esmx/rspack';
|
|
3
|
+
import { VueLoaderPlugin as VueLoader2Plugin } from 'vue2-loader';
|
|
4
|
+
import { VueLoaderPlugin as VueLoader3Plugin } from 'vue3-loader';
|
|
5
|
+
import type { RspackVueAppOptions } from './vue';
|
|
6
|
+
import { vue2Loader } from './vue2-loader';
|
|
7
|
+
import { vue3Loader } from './vue3-loader';
|
|
8
|
+
|
|
9
|
+
type VueType = '2' | '3';
|
|
10
|
+
|
|
11
|
+
export function createRspackVueApp(
|
|
12
|
+
esmx: Esmx,
|
|
13
|
+
vueType: VueType,
|
|
14
|
+
options?: RspackVueAppOptions
|
|
15
|
+
) {
|
|
16
|
+
return createRspackHtmlApp(esmx, {
|
|
17
|
+
...options,
|
|
18
|
+
loaders: {
|
|
19
|
+
styleLoader: new URL(import.meta.resolve('vue-style-loader'))
|
|
20
|
+
.pathname,
|
|
21
|
+
...options?.loaders
|
|
22
|
+
},
|
|
23
|
+
config(context) {
|
|
24
|
+
const { config, buildTarget } = context;
|
|
25
|
+
// 支持 Vue 拓展名
|
|
26
|
+
config.resolve = {
|
|
27
|
+
...config.resolve,
|
|
28
|
+
extensions: [...(config.resolve?.extensions ?? []), '.vue']
|
|
29
|
+
};
|
|
30
|
+
config.plugins = config.plugins || [];
|
|
31
|
+
switch (vueType) {
|
|
32
|
+
case '2':
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
config.plugins.push(new VueLoader2Plugin());
|
|
35
|
+
break;
|
|
36
|
+
case '3':
|
|
37
|
+
config.plugins.push(new VueLoader3Plugin());
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
// 设置 Vue 相关的环境变量
|
|
41
|
+
if (buildTarget === 'client') {
|
|
42
|
+
config.plugins.push(
|
|
43
|
+
new rspack.DefinePlugin({
|
|
44
|
+
'process.env.VUE_ENV': JSON.stringify(buildTarget)
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
// 设置 vue-loader
|
|
49
|
+
const vueRuleUse: rspack.RuleSetUse = [
|
|
50
|
+
{
|
|
51
|
+
loader: new URL(import.meta.resolve(`vue${vueType}-loader`))
|
|
52
|
+
.pathname,
|
|
53
|
+
options: {
|
|
54
|
+
...options?.vueLoader,
|
|
55
|
+
experimentalInlineMatchResource: true,
|
|
56
|
+
optimizeSSR: buildTarget === 'server'
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
switch (vueType) {
|
|
61
|
+
case '2':
|
|
62
|
+
vueRuleUse.unshift(vue2Loader);
|
|
63
|
+
break;
|
|
64
|
+
case '3':
|
|
65
|
+
vueRuleUse.unshift(vue3Loader);
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
config.module = {
|
|
69
|
+
...config.module,
|
|
70
|
+
rules: [
|
|
71
|
+
...(config.module?.rules ?? []),
|
|
72
|
+
{
|
|
73
|
+
test: /\.vue$/,
|
|
74
|
+
use: vueRuleUse
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
};
|
|
78
|
+
// 设置 vue 别名
|
|
79
|
+
let vueAlias: string | null = null;
|
|
80
|
+
switch (vueType) {
|
|
81
|
+
case '2':
|
|
82
|
+
vueAlias = 'vue/dist/vue.esm.js';
|
|
83
|
+
break;
|
|
84
|
+
case '3':
|
|
85
|
+
vueAlias = 'vue/dist/vue.runtime.esm-browser.js';
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
if (vueAlias) {
|
|
89
|
+
config.resolve!.alias = {
|
|
90
|
+
...config.resolve!.alias!,
|
|
91
|
+
vue$: vueAlias
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
// 设置 vue 相关忽略信息。
|
|
95
|
+
if (vueType === '2') {
|
|
96
|
+
config.ignoreWarnings = [
|
|
97
|
+
...(config.ignoreWarnings ?? []),
|
|
98
|
+
(warning) => {
|
|
99
|
+
// @ts-ignore
|
|
100
|
+
return warning.moduleDescriptor.name.includes(
|
|
101
|
+
'vue-server-renderer'
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
];
|
|
105
|
+
}
|
|
106
|
+
// 设置自定义配置
|
|
107
|
+
options?.config?.(context);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
package/src/vue.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Esmx } from '@esmx/core';
|
|
2
|
+
import type { RspackHtmlAppOptions } from '@esmx/rspack';
|
|
3
|
+
import { createRspackVueApp } from './vue-core';
|
|
4
|
+
|
|
5
|
+
export interface RspackVueAppOptions extends RspackHtmlAppOptions {
|
|
6
|
+
/**
|
|
7
|
+
* vue-loader 配置项
|
|
8
|
+
*
|
|
9
|
+
* 用于配置 Vue 单文件组件的编译选项,完整选项参考:
|
|
10
|
+
* https://github.com/vuejs/vue-loader
|
|
11
|
+
*/
|
|
12
|
+
vueLoader?: Record<string, any>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 创建 Vue 2 应用构建器
|
|
17
|
+
*
|
|
18
|
+
* @param esmx - Esmx 实例
|
|
19
|
+
* @param options - Rspack Vue 应用配置项
|
|
20
|
+
* @returns 返回一个 Promise,解析为构建好的应用实例
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import type { EsmxOptions } from '@esmx/core';
|
|
25
|
+
*
|
|
26
|
+
* export default {
|
|
27
|
+
* async devApp(esmx) {
|
|
28
|
+
* return import('@esmx/rspack-vue').then((m) =>
|
|
29
|
+
* m.createRspackVue2App(esmx, {
|
|
30
|
+
* config({ config }) {
|
|
31
|
+
* // 自定义 Rspack 配置
|
|
32
|
+
* }
|
|
33
|
+
* })
|
|
34
|
+
* );
|
|
35
|
+
* }
|
|
36
|
+
* } satisfies EsmxOptions;
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function createRspackVue2App(esmx: Esmx, options?: RspackVueAppOptions) {
|
|
40
|
+
return createRspackVueApp(esmx, '2', options);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 创建 Vue 3 应用构建器
|
|
45
|
+
*
|
|
46
|
+
* @param esmx - Esmx 实例
|
|
47
|
+
* @param options - Rspack Vue 应用配置项
|
|
48
|
+
* @returns 返回一个 Promise,解析为构建好的应用实例
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import type { EsmxOptions } from '@esmx/core';
|
|
53
|
+
*
|
|
54
|
+
* export default {
|
|
55
|
+
* async devApp(esmx) {
|
|
56
|
+
* return import('@esmx/rspack-vue').then((m) =>
|
|
57
|
+
* m.createRspackVue3App(esmx, {
|
|
58
|
+
* config({ config }) {
|
|
59
|
+
* // 自定义 Rspack 配置
|
|
60
|
+
* }
|
|
61
|
+
* })
|
|
62
|
+
* );
|
|
63
|
+
* }
|
|
64
|
+
* } satisfies EsmxOptions;
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export function createRspackVue3App(esmx: Esmx, options?: RspackVueAppOptions) {
|
|
68
|
+
return createRspackVueApp(esmx, '3', options);
|
|
69
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { rspack } from '@esmx/rspack';
|
|
2
|
+
const FIX_ESM = `api.install(require('vue').default)`;
|
|
3
|
+
const ADD_IMPORT = `
|
|
4
|
+
function initImport () {
|
|
5
|
+
const mixins = Array.isArray(component.options.mixins) ? component.options.mixins : [];
|
|
6
|
+
mixins.push({
|
|
7
|
+
serverPrefetch () {
|
|
8
|
+
this.$ssrContext?.importMetaSet?.add(import.meta);
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
component.options.mixins = mixins;
|
|
12
|
+
}
|
|
13
|
+
initImport();
|
|
14
|
+
export default component.exports
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
export default function (this: rspack.LoaderContext, text: string) {
|
|
18
|
+
// 修复不支持热更新的 BUG
|
|
19
|
+
text = text.replaceAll(`api.install(require('vue'))`, FIX_ESM);
|
|
20
|
+
// 添加 CSS 依赖收集
|
|
21
|
+
if (typeof this.target === 'string' && this.target.includes('node')) {
|
|
22
|
+
text = text.replaceAll('export default component.exports', ADD_IMPORT);
|
|
23
|
+
}
|
|
24
|
+
return text;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const vue2Loader = new URL(import.meta.resolve(import.meta.url))
|
|
28
|
+
.pathname;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { rspack } from '@esmx/rspack';
|
|
2
|
+
|
|
3
|
+
const ADD_IMPORT = `
|
|
4
|
+
import { useSSRContext } from 'vue';
|
|
5
|
+
function initImport () {
|
|
6
|
+
|
|
7
|
+
const mixins = Array.isArray(__exports__.mixins) ? __exports__.mixins : [];
|
|
8
|
+
mixins.push({
|
|
9
|
+
created () {
|
|
10
|
+
const ctx = useSSRContext();
|
|
11
|
+
ctx?.importMetaSet?.add(import.meta);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
__exports__.mixins = mixins;
|
|
15
|
+
}
|
|
16
|
+
initImport();
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
export default function (this: rspack.LoaderContext, text: string) {
|
|
20
|
+
return text + ADD_IMPORT;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const vue3Loader = new URL(import.meta.resolve(import.meta.url))
|
|
24
|
+
.pathname;
|