Kaynağa Gözat

添加 unplugin-vue-components 依赖并更新相关配置,调整开发服务器端口,优化样式处理,修复 HelloWorld 组件默认消息。

xbx 1 ay önce
ebeveyn
işleme
2ccd93d15c

+ 15 - 0
components.d.ts

@@ -0,0 +1,15 @@
+/* eslint-disable */
+// @ts-nocheck
+// Generated by unplugin-vue-components
+// Read more: https://github.com/vuejs/core/pull/3399
+// biome-ignore lint: disable
+export {};
+
+/* prettier-ignore */
+declare module 'vue' {
+  export interface GlobalComponents {
+    HelloWorld: typeof import('./src/components/HelloWorld.vue')['default']
+    RouterLink: typeof import('vue-router')['RouterLink']
+    RouterView: typeof import('vue-router')['RouterView']
+  }
+}

+ 3 - 1
package.json

@@ -25,7 +25,8 @@
   "dependencies": {
     "axios": "^1.9.0",
     "vue": "^3.5.13",
-    "vue-router": "^4.5.1"
+    "vue-router": "^4.5.1",
+    "webpack-merge": "^6.0.1"
   },
   "devDependencies": {
     "@rspack/cli": "^1.3.10",
@@ -50,6 +51,7 @@
     "typescript": "^5.8.3",
     "typescript-eslint": "^8.29.0",
     "unplugin-auto-import": "^19.2.0",
+    "unplugin-vue-components": "^28.7.0",
     "vue-loader": "^17.4.2"
   }
 }

+ 103 - 0
pnpm-lock.yaml

@@ -17,6 +17,9 @@ importers:
       vue-router:
         specifier: ^4.5.1
         version: 4.5.1(vue@3.5.14(typescript@5.8.3))
+      webpack-merge:
+        specifier: ^6.0.1
+        version: 6.0.1
     devDependencies:
       '@rspack/cli':
         specifier: ^1.3.10
@@ -84,6 +87,9 @@ importers:
       unplugin-auto-import:
         specifier: ^19.2.0
         version: 19.2.0
+      unplugin-vue-components:
+        specifier: ^28.7.0
+        version: 28.7.0(@babel/parser@7.27.2)(vue@3.5.14(typescript@5.8.3))
       vue-loader:
         specifier: ^17.4.2
         version: 17.4.2(vue@3.5.14(typescript@5.8.3))(webpack@5.99.8)
@@ -770,6 +776,10 @@ packages:
     resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
     engines: {node: '>=12'}
 
+  clone-deep@4.0.1:
+    resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==}
+    engines: {node: '>=6'}
+
   color-convert@2.0.1:
     resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
     engines: {node: '>=7.0.0'}
@@ -1197,6 +1207,10 @@ packages:
     resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
     engines: {node: '>=16'}
 
+  flat@5.0.2:
+    resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==}
+    hasBin: true
+
   flatted@3.3.3:
     resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
 
@@ -1447,6 +1461,10 @@ packages:
     resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==}
     engines: {node: '>=10'}
 
+  is-plain-object@2.0.4:
+    resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==}
+    engines: {node: '>=0.10.0'}
+
   is-promise@4.0.0:
     resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
 
@@ -1460,6 +1478,10 @@ packages:
   isexe@2.0.0:
     resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
 
+  isobject@3.0.1:
+    resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
+    engines: {node: '>=0.10.0'}
+
   jest-util@29.7.0:
     resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==}
     engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -1497,6 +1519,10 @@ packages:
   keyv@4.5.4:
     resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
 
+  kind-of@6.0.3:
+    resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
+    engines: {node: '>=0.10.0'}
+
   launch-editor@2.10.0:
     resolution: {integrity: sha512-D7dBRJo/qcGX9xlvt/6wUYzQxjh5G1RvZPgPv8vi4KRU99DVQL/oW7tnVOCCTm2HGeo3C5HvGE5Yrh6UBoZ0vA==}
 
@@ -2139,6 +2165,10 @@ packages:
   setprototypeof@1.2.0:
     resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
 
+  shallow-clone@3.0.1:
+    resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==}
+    engines: {node: '>=8'}
+
   shebang-command@2.0.0:
     resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
     engines: {node: '>=8'}
@@ -2309,6 +2339,10 @@ packages:
     resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==}
     engines: {node: '>=12.0.0'}
 
+  tinyglobby@0.2.14:
+    resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==}
+    engines: {node: '>=12.0.0'}
+
   to-regex-range@5.0.1:
     resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
     engines: {node: '>=8.0'}
@@ -2404,6 +2438,19 @@ packages:
     resolution: {integrity: sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==}
     engines: {node: '>=18.12.0'}
 
+  unplugin-vue-components@28.7.0:
+    resolution: {integrity: sha512-3SuWAHlTjOiZckqRBGXRdN/k6IMmKyt2Ch5/+DKwYaT321H0ItdZDvW4r8/YkEKQpN9TN3F/SZ0W342gQROC3Q==}
+    engines: {node: '>=14'}
+    peerDependencies:
+      '@babel/parser': ^7.15.8
+      '@nuxt/kit': ^3.2.2
+      vue: 2 || 3
+    peerDependenciesMeta:
+      '@babel/parser':
+        optional: true
+      '@nuxt/kit':
+        optional: true
+
   unplugin@2.3.4:
     resolution: {integrity: sha512-m4PjxTurwpWfpMomp8AptjD5yj8qEZN5uQjjGM3TAs9MWWD2tXSSNNj6jGR2FoVGod4293ytyV6SwBbertfyJg==}
     engines: {node: '>=18.12.0'}
@@ -2503,6 +2550,10 @@ packages:
       webpack-cli:
         optional: true
 
+  webpack-merge@6.0.1:
+    resolution: {integrity: sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==}
+    engines: {node: '>=18.0.0'}
+
   webpack-sources@3.2.3:
     resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
     engines: {node: '>=10.13.0'}
@@ -2533,6 +2584,9 @@ packages:
     engines: {node: '>= 8'}
     hasBin: true
 
+  wildcard@2.0.1:
+    resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==}
+
   word-wrap@1.2.5:
     resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
     engines: {node: '>=0.10.0'}
@@ -3450,6 +3504,12 @@ snapshots:
       strip-ansi: 6.0.1
       wrap-ansi: 7.0.0
 
+  clone-deep@4.0.1:
+    dependencies:
+      is-plain-object: 2.0.4
+      kind-of: 6.0.3
+      shallow-clone: 3.0.1
+
   color-convert@2.0.1:
     dependencies:
       color-name: 1.1.4
@@ -3907,6 +3967,8 @@ snapshots:
       flatted: 3.3.3
       keyv: 4.5.4
 
+  flat@5.0.2: {}
+
   flatted@3.3.3: {}
 
   follow-redirects@1.15.9: {}
@@ -4112,6 +4174,10 @@ snapshots:
 
   is-plain-obj@3.0.0: {}
 
+  is-plain-object@2.0.4:
+    dependencies:
+      isobject: 3.0.1
+
   is-promise@4.0.0: {}
 
   is-wsl@3.1.0:
@@ -4122,6 +4188,8 @@ snapshots:
 
   isexe@2.0.0: {}
 
+  isobject@3.0.1: {}
+
   jest-util@29.7.0:
     dependencies:
       '@jest/types': 29.6.3
@@ -4164,6 +4232,8 @@ snapshots:
     dependencies:
       json-buffer: 3.0.1
 
+  kind-of@6.0.3: {}
+
   launch-editor@2.10.0:
     dependencies:
       picocolors: 1.1.1
@@ -4769,6 +4839,10 @@ snapshots:
 
   setprototypeof@1.2.0: {}
 
+  shallow-clone@3.0.1:
+    dependencies:
+      kind-of: 6.0.3
+
   shebang-command@2.0.0:
     dependencies:
       shebang-regex: 3.0.0
@@ -4948,6 +5022,11 @@ snapshots:
       fdir: 6.4.4(picomatch@4.0.2)
       picomatch: 4.0.2
 
+  tinyglobby@0.2.14:
+    dependencies:
+      fdir: 6.4.4(picomatch@4.0.2)
+      picomatch: 4.0.2
+
   to-regex-range@5.0.1:
     dependencies:
       is-number: 7.0.0
@@ -5048,6 +5127,22 @@ snapshots:
       pathe: 2.0.3
       picomatch: 4.0.2
 
+  unplugin-vue-components@28.7.0(@babel/parser@7.27.2)(vue@3.5.14(typescript@5.8.3)):
+    dependencies:
+      chokidar: 3.6.0
+      debug: 4.4.1
+      local-pkg: 1.1.1
+      magic-string: 0.30.17
+      mlly: 1.7.4
+      tinyglobby: 0.2.14
+      unplugin: 2.3.4
+      unplugin-utils: 0.2.4
+      vue: 3.5.14(typescript@5.8.3)
+    optionalDependencies:
+      '@babel/parser': 7.27.2
+    transitivePeerDependencies:
+      - supports-color
+
   unplugin@2.3.4:
     dependencies:
       acorn: 8.14.1
@@ -5188,6 +5283,12 @@ snapshots:
       - supports-color
       - utf-8-validate
 
+  webpack-merge@6.0.1:
+    dependencies:
+      clone-deep: 4.0.1
+      flat: 5.0.2
+      wildcard: 2.0.1
+
   webpack-sources@3.2.3: {}
 
   webpack-virtual-modules@0.6.2: {}
@@ -5235,6 +5336,8 @@ snapshots:
     dependencies:
       isexe: 2.0.0
 
+  wildcard@2.0.1: {}
+
   word-wrap@1.2.5: {}
 
   wrap-ansi@7.0.0:

+ 52 - 22
rspack.base.config.ts

@@ -1,9 +1,12 @@
+// @ts-nocheck
 import { type RspackPluginFunction, rspack } from '@rspack/core';
 import { VueLoaderPlugin } from 'vue-loader';
 import path from 'path';
 import { isProd } from './plugin/getEnv';
 import sassEmbedded from 'sass-embedded';
 import ESLintPlugin from 'eslint-rspack-plugin';
+// import Components from 'unplugin-vue-components/rspack';
+import AutoImportPlugin from 'unplugin-auto-import/rspack';
 
 // 目标浏览器配置
 const targets = ['last 2 versions', '> 0.2%', 'not dead', 'Firefox ESR'];
@@ -75,6 +78,10 @@ export const baseConfig = {
         type: 'javascript/auto',
       },
       {
+        test: /\.d\.ts$/,
+        loader: 'ignore-loader',
+      },
+      {
         test: /\.svg/,
         type: 'asset/resource',
       },
@@ -82,41 +89,63 @@ export const baseConfig = {
         test: /\.(png|jpe?g|gif)$/i,
         type: 'asset/resource',
       },
+      // 处理CSS文件
       {
-        oneOf: [
+        test: /\.css$/i,
+        use: [
           {
-            test: /\.css$/i,
-            use: [
-              isProd() ? rspack.CssExtractRspackPlugin.loader : 'style-loader',
-              'css-loader',
-            ],
-            type: 'javascript/auto',
+            loader: isProd()
+              ? rspack.CssExtractRspackPlugin.loader
+              : 'style-loader',
+            options: {
+              publicPath: 'auto',
+            },
+          },
+          'css-loader',
+        ],
+      },
+      // 处理SCSS/SASS文件
+      {
+        test: /\.(scss|sass)$/i,
+        use: [
+          {
+            loader: isProd()
+              ? rspack.CssExtractRspackPlugin.loader
+              : 'style-loader',
+            options: {
+              publicPath: 'auto',
+            },
           },
 
+          'css-loader',
           {
-            test: /\.(sass|scss)$/,
-            use: [
-              isProd() ? rspack.CssExtractRspackPlugin.loader : 'style-loader',
-              'css-loader',
-              {
-                loader: 'sass-loader',
-                options: {
-                  api: 'modern-compiler',
-                  implementation: sassEmbedded,
-                },
-              },
-            ],
-            type: 'javascript/auto',
+            loader: 'sass-loader',
+            options: {
+              api: 'modern-compiler',
+              implementation: sassEmbedded,
+            },
           },
         ],
+        type: 'javascript/auto',
       },
     ],
   },
   plugins: [
+    new rspack.CssExtractRspackPlugin({
+      filename: '[name].[contenthash].css',
+    }),
     new rspack.HtmlRspackPlugin({
       template: './index.html',
     }),
-    require('unplugin-auto-import/rspack').default({
+    // Components({
+    //   dirs: ['src/components'],
+    //   extensions: ['vue'],
+    //   deep: true,
+    //   dts: true,
+    //   directoryAsNamespace: false,
+    //   directives: true,
+    // }),
+    AutoImportPlugin({
       include: [
         /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
         /\.vue$/,
@@ -171,6 +200,7 @@ export const baseConfig = {
     ],
   },
   experiments: {
-    css: true,
+    futureDefaults: true,
+    css: false,
   },
 };

+ 1 - 0
rspack.config.ts

@@ -1,3 +1,4 @@
+// @ts-nocheck
 import { defineConfig } from '@rspack/cli';
 import { isDev } from './plugin/getEnv';
 import devConfig from './rspack.dev.config';

+ 27 - 28
rspack.dev.config.ts

@@ -1,32 +1,31 @@
+/// <reference path="./tsconfig.node.json" />
+// @ts-nocheck
 import { defineConfig } from '@rspack/cli';
-
+import { merge } from 'webpack-merge';
 import { baseConfig } from './rspack.base.config';
 
-export default defineConfig({
-  ...baseConfig,
-  mode: 'development',
-  entry: {
-    main: './src/main.ts',
-  },
-  devtool: 'eval-cheap-module-source-map',
-  devServer: {
-    hot: true,
-    port: 8089,
-    open: true,
-    historyApiFallback: true,
-    proxy: [
-      {
-        context: ['/api'],
-        target: 'http://localhost:3000',
-        changeOrigin: true,
-        pathRewrite: {
-          '^/api': '',
+export default defineConfig(
+  merge(baseConfig, {
+    mode: 'development',
+    entry: {
+      main: './src/main.ts',
+    },
+    devtool: 'eval-cheap-module-source-map',
+    devServer: {
+      hot: true,
+      port: 8093,
+      open: true,
+      historyApiFallback: true,
+      proxy: [
+        {
+          context: ['/api'],
+          target: 'http://localhost:3000',
+          changeOrigin: true,
+          pathRewrite: {
+            '^/api': '',
+          },
         },
-      },
-    ],
-  },
-
-  experiments: {
-    css: true,
-  },
-});
+      ],
+    },
+  }),
+);

+ 60 - 60
rspack.prod.config.ts

@@ -1,68 +1,68 @@
+// @ts-nocheck
 import { defineConfig } from '@rspack/cli';
 import { rspack } from '@rspack/core';
+import { merge } from 'webpack-merge';
 import { baseConfig } from './rspack.base.config';
 
-export default defineConfig({
-  ...baseConfig,
-  mode: 'production',
-  entry: {
-    main: './src/main.ts',
-  },
-  devtool: false,
-  output: {
-    clean: true,
-    filename: '[name].[contenthash].js',
-    chunkFilename: '[name].[contenthash].js',
-  },
-  optimization: {
-    minimize: true,
-    minimizer: [
-      new rspack.SwcJsMinimizerRspackPlugin(),
-      new rspack.LightningCssMinimizerRspackPlugin(),
-    ],
-    splitChunks: {
-      chunks: 'async',
-      minChunks: 1,
-      minSize: 2000,
-      maxAsyncRequests: 30,
-      maxInitialRequests: 30,
-      cacheGroups: {
-        'vue-router': {
-          name: 'vue-router',
-          test: /[\\/]node_modules[\\/]vue-router[\\/]/,
-          priority: 120,
-          chunks: 'all',
-          reuseExistingChunk: true,
-        },
+export default defineConfig(
+  merge(baseConfig, {
+    mode: 'production',
+    entry: {
+      main: './src/main.ts',
+    },
+    devtool: false,
+    output: {
+      clean: true,
+      filename: '[name].[contenthash].js',
+      chunkFilename: '[name].[contenthash].js',
+    },
+    optimization: {
+      minimize: true,
+      minimizer: [
+        new rspack.SwcJsMinimizerRspackPlugin(),
+        new rspack.LightningCssMinimizerRspackPlugin(),
+      ],
+      splitChunks: {
+        chunks: 'async',
+        minChunks: 1,
+        minSize: 2000,
+        maxAsyncRequests: 30,
+        maxInitialRequests: 30,
+        cacheGroups: {
+          'vue-router': {
+            name: 'vue-router',
+            test: /[\\/]node_modules[\\/]vue-router[\\/]/,
+            priority: 120,
+            chunks: 'all',
+            reuseExistingChunk: true,
+          },
 
-        vue: {
-          name: 'vue',
-          test: /[\\/]node_modules[\\/]vue[\\/]/,
-          priority: 200,
-          chunks: 'all',
-          reuseExistingChunk: true,
-        },
-        axios: {
-          name: 'axios',
-          test: /[\\/]node_modules[\\/]axios[\\/]/,
-          priority: 9,
-          chunks: 'all',
-          reuseExistingChunk: true,
-        },
-        defaultVendors: {
-          test: /[\\/]node_modules[\\/]/,
-          priority: -10,
-          reuseExistingChunk: true,
-        },
-        default: {
-          minChunks: 2,
-          priority: -20,
-          reuseExistingChunk: true,
+          vue: {
+            name: 'vue',
+            test: /[\\/]node_modules[\\/]vue[\\/]/,
+            priority: 200,
+            chunks: 'all',
+            reuseExistingChunk: true,
+          },
+          axios: {
+            name: 'axios',
+            test: /[\\/]node_modules[\\/]axios[\\/]/,
+            priority: 9,
+            chunks: 'all',
+            reuseExistingChunk: true,
+          },
+          defaultVendors: {
+            test: /[\\/]node_modules[\\/]/,
+            priority: -10,
+            reuseExistingChunk: true,
+          },
+          default: {
+            minChunks: 2,
+            priority: -20,
+            reuseExistingChunk: true,
+          },
         },
       },
     },
-  },
-  experiments: {
-    css: true,
-  },
-});
+  }),
+);

+ 24 - 19
src/App.vue

@@ -1,35 +1,40 @@
 <script setup lang="ts">
-import { ref } from "vue";
-import HelloWorld from "./components/HelloWorld.vue";
+import { ref } from 'vue';
+import HelloWorld from './components/HelloWorld.vue';
 
-const title = ref<string>("Rspack + Vue");
+const title = ref<string>('Rspack + Vue');
 </script>
 
 <template>
-	<div>
-		<a href="https://www.rspack.dev/" target="_blank">
-			<img src="./assets/rspack.svg" class="logo" alt="Rspack logo" />
-		</a>
-		<a href="https://vuejs.org/" target="_blank">
-			<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
-		</a>
-	</div>
-	<HelloWorld :msg="title" />
+  <div>
+    <a href="https://www.rspack.dev/" target="_blank">
+      <img src="./assets/rspack.svg" class="logo" alt="Rspack logo" />
+    </a>
+    <a href="https://vuejs.org/" target="_blank">
+      <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
+    </a>
+  </div>
+  <HelloWorld :msg="title" />
 </template>
 
-<style scoped>
+<style scoped lang="css">
 .logo {
-	height: 6em;
-	padding: 1.5em;
-	will-change: filter;
-	transition: filter 300ms;
+  height: 6em;
+  padding: 1.5em;
+  will-change: filter;
+  transition: filter 300ms;
 }
 
 .logo:hover {
-	filter: drop-shadow(0 0 2em #646cffaa);
+  filter: drop-shadow(0 0 2em #646cffaa);
 }
 
 .logo.vue:hover {
-	filter: drop-shadow(0 0 2em #42b883aa);
+  filter: drop-shadow(0 0 2em #42b883aa);
+}
+</style>
+<style lang="scss">
+#app {
+  background-color: #000;
 }
 </style>

+ 21 - 20
src/components/HelloWorld.vue

@@ -1,36 +1,37 @@
 <script setup lang="ts">
-import { ref } from "vue";
+import { ref } from 'vue';
 
 defineProps({
-	msg: {
-		type: String
-	}
+  msg: {
+    type: String,
+    default: 'Hello World',
+  },
 });
 const count = ref<number>(0);
 </script>
 
 <template>
-	<h1>{{ msg }}</h1>
+  <h1>{{ msg }}</h1>
 
-	<div class="card">
-		<button type="button" @click="count++">count is {{ count }}</button>
-		<p>
-			Edit
-			<code>components/HelloWorld.vue</code> to test HMR
-		</p>
-	</div>
+  <div class="card">
+    <button type="button" @click="count++">count is {{ count }}</button>
+    <p>
+      Edit
+      <code>components/HelloWorld.vue</code> to test HMR
+    </p>
+  </div>
 
-	<p>Check out Rspack which support Vue</p>
-	<p>
-		Install
-		<a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>
-		in your IDE for a better DX
-	</p>
-	<p class="read-the-docs">Click on the Rspack and Vue logos to learn more</p>
+  <p>Check out Rspack which support Vue</p>
+  <p>
+    Install
+    <a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>
+    in your IDE for a better DX
+  </p>
+  <p class="read-the-docs">Click on the Rspack and Vue logos to learn more</p>
 </template>
 
 <style scoped>
 .read-the-docs {
-	color: #888;
+  color: #888;
 }
 </style>

+ 93 - 0
src/types/auto-imports.d.ts

@@ -0,0 +1,93 @@
+/* eslint-disable */
+/* prettier-ignore */
+// @ts-nocheck
+// noinspection JSUnusedGlobalSymbols
+// Generated by unplugin-auto-import
+// biome-ignore lint: disable
+export {}
+declare global {
+  const EffectScope: (typeof import('vue'))['EffectScope'];
+  const computed: (typeof import('vue'))['computed'];
+  const createApp: (typeof import('vue'))['createApp'];
+  const customRef: (typeof import('vue'))['customRef'];
+  const defineAsyncComponent: (typeof import('vue'))['defineAsyncComponent'];
+  const defineComponent: (typeof import('vue'))['defineComponent'];
+  const effectScope: (typeof import('vue'))['effectScope'];
+  const getCurrentInstance: (typeof import('vue'))['getCurrentInstance'];
+  const getCurrentScope: (typeof import('vue'))['getCurrentScope'];
+  const h: (typeof import('vue'))['h'];
+  const inject: (typeof import('vue'))['inject'];
+  const isProxy: (typeof import('vue'))['isProxy'];
+  const isReactive: (typeof import('vue'))['isReactive'];
+  const isReadonly: (typeof import('vue'))['isReadonly'];
+  const isRef: (typeof import('vue'))['isRef'];
+  const markRaw: (typeof import('vue'))['markRaw'];
+  const nextTick: (typeof import('vue'))['nextTick'];
+  const onActivated: (typeof import('vue'))['onActivated'];
+  const onBeforeMount: (typeof import('vue'))['onBeforeMount'];
+  const onBeforeRouteLeave: (typeof import('vue-router'))['onBeforeRouteLeave'];
+  const onBeforeRouteUpdate: (typeof import('vue-router'))['onBeforeRouteUpdate'];
+  const onBeforeUnmount: (typeof import('vue'))['onBeforeUnmount'];
+  const onBeforeUpdate: (typeof import('vue'))['onBeforeUpdate'];
+  const onDeactivated: (typeof import('vue'))['onDeactivated'];
+  const onErrorCaptured: (typeof import('vue'))['onErrorCaptured'];
+  const onMounted: (typeof import('vue'))['onMounted'];
+  const onRenderTracked: (typeof import('vue'))['onRenderTracked'];
+  const onRenderTriggered: (typeof import('vue'))['onRenderTriggered'];
+  const onScopeDispose: (typeof import('vue'))['onScopeDispose'];
+  const onServerPrefetch: (typeof import('vue'))['onServerPrefetch'];
+  const onUnmounted: (typeof import('vue'))['onUnmounted'];
+  const onUpdated: (typeof import('vue'))['onUpdated'];
+  const onWatcherCleanup: (typeof import('vue'))['onWatcherCleanup'];
+  const provide: (typeof import('vue'))['provide'];
+  const reactive: (typeof import('vue'))['reactive'];
+  const readonly: (typeof import('vue'))['readonly'];
+  const ref: (typeof import('vue'))['ref'];
+  const resolveComponent: (typeof import('vue'))['resolveComponent'];
+  const shallowReactive: (typeof import('vue'))['shallowReactive'];
+  const shallowReadonly: (typeof import('vue'))['shallowReadonly'];
+  const shallowRef: (typeof import('vue'))['shallowRef'];
+  const toRaw: (typeof import('vue'))['toRaw'];
+  const toRef: (typeof import('vue'))['toRef'];
+  const toRefs: (typeof import('vue'))['toRefs'];
+  const toValue: (typeof import('vue'))['toValue'];
+  const triggerRef: (typeof import('vue'))['triggerRef'];
+  const unref: (typeof import('vue'))['unref'];
+  const useAttrs: (typeof import('vue'))['useAttrs'];
+  const useCssModule: (typeof import('vue'))['useCssModule'];
+  const useCssVars: (typeof import('vue'))['useCssVars'];
+  const useId: (typeof import('vue'))['useId'];
+  const useLink: (typeof import('vue-router'))['useLink'];
+  const useModel: (typeof import('vue'))['useModel'];
+  const useRoute: (typeof import('vue-router'))['useRoute'];
+  const useRouter: (typeof import('vue-router'))['useRouter'];
+  const useSlots: (typeof import('vue'))['useSlots'];
+  const useTemplateRef: (typeof import('vue'))['useTemplateRef'];
+  const watch: (typeof import('vue'))['watch'];
+  const watchEffect: (typeof import('vue'))['watchEffect'];
+  const watchPostEffect: (typeof import('vue'))['watchPostEffect'];
+  const watchSyncEffect: (typeof import('vue'))['watchSyncEffect'];
+}
+// for type re-export
+declare global {
+  // @ts-ignore
+  export type {
+    Component,
+    Slot,
+    Slots,
+    ComponentPublicInstance,
+    ComputedRef,
+    DirectiveBinding,
+    ExtractDefaultPropTypes,
+    ExtractPropTypes,
+    ExtractPublicPropTypes,
+    InjectionKey,
+    PropType,
+    Ref,
+    MaybeRef,
+    MaybeRefOrGetter,
+    VNode,
+    WritableComputedRef,
+  } from 'vue';
+  import('vue');
+}

+ 2 - 1
tsconfig.json

@@ -15,12 +15,13 @@
     "allowImportingTsExtensions": true
   },
   "include": ["src"],
+  "exclude": ["./rspack.*.config.ts", "rspack.config.ts"],
   "ts-node": {
     "compilerOptions": {
       "module": "CommonJS",
       "esModuleInterop": true, // 启用实验性的 ECMAScript 模块互操作性,方便导入 CommonJS 模块
       "skipLibCheck": true, // 跳过对库文件的类型检查,可以加快编译速度,
-      "forceConsistentCasingInFileNames": true  // 强制文件名大小写一致,避免在不同文件系统中出现文件名大小写不一致的问题
+      "forceConsistentCasingInFileNames": true // 强制文件名大小写一致,避免在不同文件系统中出现文件名大小写不一致的问题
     }
   }
 }

+ 12 - 0
tsconfig.node.json

@@ -0,0 +1,12 @@
+{
+  "compilerOptions": {
+    "composite": true,
+    "skipLibCheck": true,
+    "module": "ESNext",
+    "moduleResolution": "bundler",
+    "allowSyntheticDefaultImports": true,
+    "strict": false,
+    "noImplicitAny": false
+  },
+  "include": ["rspack.*.config.ts", "rspack.config.ts", "plugin/**/*"]
+}