diff --git a/.changeset/real-cars-chew.md b/.changeset/real-cars-chew.md new file mode 100644 index 000000000000..8cefb52452e0 --- /dev/null +++ b/.changeset/real-cars-chew.md @@ -0,0 +1,7 @@ +--- +'@modern-js/builder-plugin-vue2': patch +--- + +feat(builder): add new builder-plugin-vue2 + +feat(builder): 新增 builder-plugin-vue2 插件 diff --git a/packages/builder/plugin-vue2/.eslintrc.js b/packages/builder/plugin-vue2/.eslintrc.js new file mode 100644 index 000000000000..f9da2e208b89 --- /dev/null +++ b/packages/builder/plugin-vue2/.eslintrc.js @@ -0,0 +1,11 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + extends: ['@modern-js'], + ignorePatterns: ['vitest.config.ts'], + parserOptions: { + project: require.resolve('./tsconfig.json'), + }, + rules: { + 'import/order': 0, + }, +}; diff --git a/packages/builder/plugin-vue2/.npmignore b/packages/builder/plugin-vue2/.npmignore new file mode 100644 index 000000000000..5faf67231f9d --- /dev/null +++ b/packages/builder/plugin-vue2/.npmignore @@ -0,0 +1,23 @@ +.DS_Store + +*.log* +*.pid +*.pid.* +*.report + +node_modules/ +.nyc_output +*.tsbuildinfo +.eslintcache +.sonarlint + +coverage/ +tests/ + +src/ + +modern.config.js +modern.config.ts +vitest.config.ts +.eslintrc.js +tsconfig.json diff --git a/packages/builder/plugin-vue2/CHANGELOG.md b/packages/builder/plugin-vue2/CHANGELOG.md new file mode 100644 index 000000000000..262b999e9377 --- /dev/null +++ b/packages/builder/plugin-vue2/CHANGELOG.md @@ -0,0 +1 @@ +# @modern-js/builder-plugin-vue2 diff --git a/packages/builder/plugin-vue2/LICENSE b/packages/builder/plugin-vue2/LICENSE new file mode 100644 index 000000000000..a33f52674491 --- /dev/null +++ b/packages/builder/plugin-vue2/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Modern.js + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/builder/plugin-vue2/README.md b/packages/builder/plugin-vue2/README.md new file mode 100644 index 000000000000..0c1cc1d4e71f --- /dev/null +++ b/packages/builder/plugin-vue2/README.md @@ -0,0 +1,26 @@ + +

+ Modern.js Logo +

+

+ Modern.js Builder +
+ + modernjs.dev/builder + +

+

+ A build engine for web development. +

+ +# @modern-js/builder-plugin-vue2 + +This package is the Vue 2 plugin of Modern.js Builder. + +## Getting Started + +- [Documentation](https://modernjs.dev/builder/en/plugins/plugin-vue2.html) + +## Contributing + +- [Contributing Guide](https://github.com/web-infra-dev/modern.js/blob/main/CONTRIBUTING.md) diff --git a/packages/builder/plugin-vue2/modern.config.js b/packages/builder/plugin-vue2/modern.config.js new file mode 100644 index 000000000000..c2bf3e85b393 --- /dev/null +++ b/packages/builder/plugin-vue2/modern.config.js @@ -0,0 +1,5 @@ +const { tscLikeBuildConfig } = require('@scripts/build'); + +module.exports = { + buildConfig: tscLikeBuildConfig, +}; diff --git a/packages/builder/plugin-vue2/package.json b/packages/builder/plugin-vue2/package.json new file mode 100644 index 000000000000..ef102fbb0efc --- /dev/null +++ b/packages/builder/plugin-vue2/package.json @@ -0,0 +1,75 @@ +{ + "name": "@modern-js/builder-plugin-vue2", + "description": "Vue 2 plugin of Modern.js Builder", + "homepage": "https://modernjs.dev/builder", + "bugs": "https://github.com/web-infra-dev/modern.js/issues", + "repository": { + "type": "git", + "url": "https://github.com/web-infra-dev/modern.js", + "directory": "packages/builder/plugin-vue" + }, + "license": "MIT", + "keywords": [ + "react", + "framework", + "modern", + "modern.js" + ], + "engines": { + "node": ">=14.0.0" + }, + "version": "2.26.0", + "jsnext:source": "./src/index.ts", + "types": "./src/index.ts", + "main": "./dist/index.js", + "module": "./dist/index.js", + "exports": { + ".": { + "jsnext:source": "./src/index.ts", + "default": "./dist/index.js" + } + }, + "scripts": { + "prepublishOnly": "only-allow-pnpm", + "new": "modern new", + "build": "modern-lib build", + "dev": "modern-lib build --watch", + "test": "vitest run", + "test:watch": "vitest dev --no-coverage" + }, + "dependencies": { + "@modern-js/builder-shared": "workspace:*", + "@swc/helpers": "0.5.1", + "@vue/babel-preset-jsx": "^1.4.0", + "vue-loader": "^15.10.1" + }, + "devDependencies": { + "@babel/core": "^7.21.8", + "@modern-js/builder": "workspace:*", + "@modern-js/builder-webpack-provider": "workspace:*", + "@modern-js/builder-rspack-provider": "workspace:*", + "@modern-js/utils": "workspace:*", + "@scripts/build": "workspace:*", + "@scripts/vitest-config": "workspace:*", + "typescript": "^5", + "webpack": "^5.88.1" + }, + "peerDependencies": { + "@modern-js/builder-webpack-provider": "workspace:^2.26.0", + "@modern-js/builder-rspack-provider": "workspace:^2.26.0" + }, + "peerDependenciesMeta": { + "@modern-js/builder-webpack-provider": { + "optional": true + }, + "@modern-js/builder-rspack-provider": { + "optional": true + } + }, + "sideEffects": false, + "publishConfig": { + "registry": "https://registry.npmjs.org/", + "access": "public", + "types": "./dist/index.d.ts" + } +} diff --git a/packages/builder/plugin-vue2/src/index.ts b/packages/builder/plugin-vue2/src/index.ts new file mode 100644 index 000000000000..f6b4b958fd23 --- /dev/null +++ b/packages/builder/plugin-vue2/src/index.ts @@ -0,0 +1,79 @@ +import { merge as deepMerge } from '@modern-js/utils/lodash'; +import { VueLoaderPlugin } from 'vue-loader'; +import type { BuilderPlugin } from '@modern-js/builder'; +import type { BuilderPluginAPI } from '@modern-js/builder-webpack-provider'; +import type { VueLoaderOptions } from 'vue-loader'; + +type VueJSXPresetOptions = { + compositionAPI?: boolean | string; + functional?: boolean; + injectH?: boolean; + vModel?: boolean; + vOn?: boolean; +}; + +export type PluginVueOptions = { + vueJsxOptions?: VueJSXPresetOptions; + vueLoaderOptions?: VueLoaderOptions; +}; + +export function builderPluginVue2( + options: PluginVueOptions = {}, +): BuilderPlugin { + return { + name: 'builder-plugin-vue2', + + // Remove built-in react plugins. + // These plugins should be moved to a separate package in the next major version. + remove: [ + 'builder-plugin-react', + 'builder-plugin-antd', + 'builder-plugin-arco', + ], + + async setup(api) { + api.modifyBuilderConfig((config, { mergeBuilderConfig }) => { + return mergeBuilderConfig(config, { + output: { + disableSvgr: true, + }, + tools: { + babel(_, { addPresets }) { + addPresets([ + [ + require.resolve('@vue/babel-preset-jsx'), + { + injectH: true, + ...options.vueJsxOptions, + }, + ], + ]); + }, + }, + }); + }); + + api.modifyBundlerChain(async (chain, { CHAIN_ID }) => { + chain.resolve.extensions.add('.vue'); + + const vueLoaderOptions = deepMerge( + { + compilerOptions: { + preserveWhitespace: false, + }, + }, + options.vueLoaderOptions, + ); + + chain.module + .rule(CHAIN_ID.RULE.VUE) + .test(/\.vue$/) + .use(CHAIN_ID.USE.VUE) + .loader(require.resolve('vue-loader')) + .options(vueLoaderOptions); + + chain.plugin(CHAIN_ID.PLUGIN.VUE_LOADER_PLUGIN).use(VueLoaderPlugin); + }); + }, + }; +} diff --git a/packages/builder/plugin-vue2/tests/.eslintrc.js b/packages/builder/plugin-vue2/tests/.eslintrc.js new file mode 100644 index 000000000000..8ad708bcff41 --- /dev/null +++ b/packages/builder/plugin-vue2/tests/.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + extends: ['@modern-js'], + parserOptions: { + project: require.resolve('./tsconfig.json'), + }, +}; diff --git a/packages/builder/plugin-vue2/tests/__snapshots__/index.test.ts.snap b/packages/builder/plugin-vue2/tests/__snapshots__/index.test.ts.snap new file mode 100644 index 000000000000..c444d19689fb --- /dev/null +++ b/packages/builder/plugin-vue2/tests/__snapshots__/index.test.ts.snap @@ -0,0 +1,556 @@ +// Vitest Snapshot v1 + +exports[`plugins/vue > should add vue-loader and VueLoaderPlugin correctly 1`] = ` +{ + "module": { + "rules": [ + { + "test": /\\\\\\.vue\\$/, + "use": [ + { + "loader": "/node_modules//vue-loader/lib/index.js", + "options": { + "compilerOptions": { + "preserveWhitespace": false, + }, + }, + }, + ], + }, + ], + }, + "plugins": [ + VueLoaderPlugin {}, + ], + "resolve": { + "extensions": [ + ".vue", + ], + }, +} +`; + +exports[`plugins/vue > should allow to configure jsx babel plugin options 1`] = ` +{ + "module": { + "rules": [ + { + "test": /\\\\\\.vue\\$/, + "use": [ + { + "loader": "/node_modules//vue-loader/lib/index.js", + "options": { + "compilerOptions": { + "preserveWhitespace": false, + }, + }, + }, + ], + }, + { + "include": [ + { + "and": [ + "", + { + "not": /node_modules/, + }, + ], + }, + ], + "test": /\\\\\\.\\(js\\|mjs\\|cjs\\|jsx\\)\\$\\|\\\\\\.\\(ts\\|mts\\|cts\\|tsx\\)\\$/, + "use": [ + { + "loader": "/packages/builder/builder-shared/compiled/babel-loader", + "options": { + "babelrc": false, + "compact": false, + "configFile": false, + "plugins": [ + [ + "/packages/cli/babel-preset-app/src/babelPluginLockCorejsVersion", + ], + [ + "/packages/cli/babel-preset-base/compiled/babel-plugin-dynamic-import-node/index.js", + ], + [ + "/packages/cli/babel-preset-base/compiled/babel-plugin-lodash/index.js", + {}, + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-decorators/index.js", + { + "legacy": true, + }, + ], + [ + "/node_modules//@babel/plugin-transform-runtime/lib/index.js", + { + "helpers": false, + "regenerator": true, + "useESModules": true, + "version": "7.21.5", + }, + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-export-default-from/index.js", + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-pipeline-operator/index.js", + { + "proposal": "minimal", + }, + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-partial-application/index.js", + ], + [ + "/packages/cli/babel-preset-base/compiled/babel-plugin-styled-components/index.js", + { + "displayName": true, + "pure": false, + "ssr": false, + "transpileTemplateLiterals": true, + }, + "styled-components", + ], + ], + "presets": [ + [ + "/node_modules//@babel/preset-env/lib/index.js", + { + "bugfixes": false, + "corejs": { + "proposals": true, + "version": "3.30", + }, + "exclude": [ + "transform-typeof-symbol", + ], + "modules": false, + "shippedProposals": false, + "targets": [ + "> 0.01%", + "not dead", + "not op_mini all", + ], + "useBuiltIns": "entry", + }, + ], + [ + "/node_modules//@babel/preset-typescript/lib/index.js", + { + "allExtensions": true, + "allowDeclareFields": true, + "allowNamespaces": true, + "isTSX": true, + "optimizeConstEnums": true, + }, + ], + [ + "/node_modules//@vue/babel-preset-jsx/dist/plugin.cjs.js", + { + "injectH": false, + }, + ], + ], + }, + }, + ], + }, + { + "mimetype": { + "or": [ + "text/javascript", + "application/javascript", + ], + }, + "use": [ + { + "loader": "/packages/builder/builder-shared/compiled/babel-loader", + "options": { + "babelrc": false, + "compact": false, + "configFile": false, + "plugins": [ + [ + "/packages/cli/babel-preset-app/src/babelPluginLockCorejsVersion", + ], + [ + "/packages/cli/babel-preset-base/compiled/babel-plugin-dynamic-import-node/index.js", + ], + [ + "/packages/cli/babel-preset-base/compiled/babel-plugin-lodash/index.js", + {}, + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-decorators/index.js", + { + "legacy": true, + }, + ], + [ + "/node_modules//@babel/plugin-transform-runtime/lib/index.js", + { + "helpers": false, + "regenerator": true, + "useESModules": true, + "version": "7.21.5", + }, + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-export-default-from/index.js", + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-pipeline-operator/index.js", + { + "proposal": "minimal", + }, + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-partial-application/index.js", + ], + [ + "/packages/cli/babel-preset-base/compiled/babel-plugin-styled-components/index.js", + { + "displayName": true, + "pure": false, + "ssr": false, + "transpileTemplateLiterals": true, + }, + "styled-components", + ], + ], + "presets": [ + [ + "/node_modules//@babel/preset-env/lib/index.js", + { + "bugfixes": false, + "corejs": { + "proposals": true, + "version": "3.30", + }, + "exclude": [ + "transform-typeof-symbol", + ], + "modules": false, + "shippedProposals": false, + "targets": [ + "> 0.01%", + "not dead", + "not op_mini all", + ], + "useBuiltIns": "entry", + }, + ], + [ + "/node_modules//@babel/preset-typescript/lib/index.js", + { + "allExtensions": true, + "allowDeclareFields": true, + "allowNamespaces": true, + "isTSX": true, + "optimizeConstEnums": true, + }, + ], + [ + "/node_modules//@vue/babel-preset-jsx/dist/plugin.cjs.js", + { + "injectH": false, + }, + ], + ], + }, + }, + ], + }, + ], + }, + "plugins": [ + VueLoaderPlugin {}, + ], + "resolve": { + "extensions": [ + ".vue", + ], + }, +} +`; + +exports[`plugins/vue > should allow to configure vueLoader options 1`] = ` +{ + "module": { + "rules": [ + { + "test": /\\\\\\.vue\\$/, + "use": [ + { + "loader": "/node_modules//vue-loader/lib/index.js", + "options": { + "compilerOptions": { + "preserveWhitespace": false, + }, + "hotReload": false, + }, + }, + ], + }, + ], + }, + "plugins": [ + VueLoaderPlugin {}, + ], + "resolve": { + "extensions": [ + ".vue", + ], + }, +} +`; + +exports[`plugins/vue > should apply jsx babel plugin correctly 1`] = ` +{ + "module": { + "rules": [ + { + "test": /\\\\\\.vue\\$/, + "use": [ + { + "loader": "/node_modules//vue-loader/lib/index.js", + "options": { + "compilerOptions": { + "preserveWhitespace": false, + }, + }, + }, + ], + }, + { + "include": [ + { + "and": [ + "", + { + "not": /node_modules/, + }, + ], + }, + ], + "test": /\\\\\\.\\(js\\|mjs\\|cjs\\|jsx\\)\\$\\|\\\\\\.\\(ts\\|mts\\|cts\\|tsx\\)\\$/, + "use": [ + { + "loader": "/packages/builder/builder-shared/compiled/babel-loader", + "options": { + "babelrc": false, + "compact": false, + "configFile": false, + "plugins": [ + [ + "/packages/cli/babel-preset-app/src/babelPluginLockCorejsVersion", + ], + [ + "/packages/cli/babel-preset-base/compiled/babel-plugin-dynamic-import-node/index.js", + ], + [ + "/packages/cli/babel-preset-base/compiled/babel-plugin-lodash/index.js", + {}, + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-decorators/index.js", + { + "legacy": true, + }, + ], + [ + "/node_modules//@babel/plugin-transform-runtime/lib/index.js", + { + "helpers": false, + "regenerator": true, + "useESModules": true, + "version": "7.21.5", + }, + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-export-default-from/index.js", + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-pipeline-operator/index.js", + { + "proposal": "minimal", + }, + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-partial-application/index.js", + ], + [ + "/packages/cli/babel-preset-base/compiled/babel-plugin-styled-components/index.js", + { + "displayName": true, + "pure": false, + "ssr": false, + "transpileTemplateLiterals": true, + }, + "styled-components", + ], + ], + "presets": [ + [ + "/node_modules//@babel/preset-env/lib/index.js", + { + "bugfixes": false, + "corejs": { + "proposals": true, + "version": "3.30", + }, + "exclude": [ + "transform-typeof-symbol", + ], + "modules": false, + "shippedProposals": false, + "targets": [ + "> 0.01%", + "not dead", + "not op_mini all", + ], + "useBuiltIns": "entry", + }, + ], + [ + "/node_modules//@babel/preset-typescript/lib/index.js", + { + "allExtensions": true, + "allowDeclareFields": true, + "allowNamespaces": true, + "isTSX": true, + "optimizeConstEnums": true, + }, + ], + [ + "/node_modules//@vue/babel-preset-jsx/dist/plugin.cjs.js", + { + "injectH": true, + }, + ], + ], + }, + }, + ], + }, + { + "mimetype": { + "or": [ + "text/javascript", + "application/javascript", + ], + }, + "use": [ + { + "loader": "/packages/builder/builder-shared/compiled/babel-loader", + "options": { + "babelrc": false, + "compact": false, + "configFile": false, + "plugins": [ + [ + "/packages/cli/babel-preset-app/src/babelPluginLockCorejsVersion", + ], + [ + "/packages/cli/babel-preset-base/compiled/babel-plugin-dynamic-import-node/index.js", + ], + [ + "/packages/cli/babel-preset-base/compiled/babel-plugin-lodash/index.js", + {}, + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-decorators/index.js", + { + "legacy": true, + }, + ], + [ + "/node_modules//@babel/plugin-transform-runtime/lib/index.js", + { + "helpers": false, + "regenerator": true, + "useESModules": true, + "version": "7.21.5", + }, + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-export-default-from/index.js", + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-pipeline-operator/index.js", + { + "proposal": "minimal", + }, + ], + [ + "/packages/cli/babel-preset-base/compiled/@babel/plugin-proposal-partial-application/index.js", + ], + [ + "/packages/cli/babel-preset-base/compiled/babel-plugin-styled-components/index.js", + { + "displayName": true, + "pure": false, + "ssr": false, + "transpileTemplateLiterals": true, + }, + "styled-components", + ], + ], + "presets": [ + [ + "/node_modules//@babel/preset-env/lib/index.js", + { + "bugfixes": false, + "corejs": { + "proposals": true, + "version": "3.30", + }, + "exclude": [ + "transform-typeof-symbol", + ], + "modules": false, + "shippedProposals": false, + "targets": [ + "> 0.01%", + "not dead", + "not op_mini all", + ], + "useBuiltIns": "entry", + }, + ], + [ + "/node_modules//@babel/preset-typescript/lib/index.js", + { + "allExtensions": true, + "allowDeclareFields": true, + "allowNamespaces": true, + "isTSX": true, + "optimizeConstEnums": true, + }, + ], + [ + "/node_modules//@vue/babel-preset-jsx/dist/plugin.cjs.js", + { + "injectH": true, + }, + ], + ], + }, + }, + ], + }, + ], + }, + "plugins": [ + VueLoaderPlugin {}, + ], + "resolve": { + "extensions": [ + ".vue", + ], + }, +} +`; diff --git a/packages/builder/plugin-vue2/tests/index.test.ts b/packages/builder/plugin-vue2/tests/index.test.ts new file mode 100644 index 000000000000..c26a51e54d08 --- /dev/null +++ b/packages/builder/plugin-vue2/tests/index.test.ts @@ -0,0 +1,55 @@ +import { expect, describe, it } from 'vitest'; +import { createStubBuilder } from '@modern-js/builder-webpack-provider/stub'; +import { builderPluginBabel } from '@modern-js/builder-webpack-provider/plugins/babel'; +import { builderPluginVue2 } from '../src'; + +describe('plugins/vue', () => { + it('should add vue-loader and VueLoaderPlugin correctly', async () => { + const builder = await createStubBuilder({ + plugins: [builderPluginVue2()], + }); + const config = await builder.unwrapWebpackConfig(); + + expect(config).toMatchSnapshot(); + }); + + it('should allow to configure vueLoader options', async () => { + const builder = await createStubBuilder({ + plugins: [ + builderPluginVue2({ + vueLoaderOptions: { + hotReload: false, + }, + }), + ], + }); + const config = await builder.unwrapWebpackConfig(); + + expect(config).toMatchSnapshot(); + }); + + it('should apply jsx babel plugin correctly', async () => { + const builder = await createStubBuilder({ + plugins: [builderPluginVue2(), builderPluginBabel()], + }); + const config = await builder.unwrapWebpackConfig(); + + expect(config).toMatchSnapshot(); + }); + + it('should allow to configure jsx babel plugin options', async () => { + const builder = await createStubBuilder({ + plugins: [ + builderPluginVue2({ + vueJsxOptions: { + injectH: false, + }, + }), + builderPluginBabel(), + ], + }); + const config = await builder.unwrapWebpackConfig(); + + expect(config).toMatchSnapshot(); + }); +}); diff --git a/packages/builder/plugin-vue2/tests/setup.ts b/packages/builder/plugin-vue2/tests/setup.ts new file mode 100644 index 000000000000..f1f04eaf82fe --- /dev/null +++ b/packages/builder/plugin-vue2/tests/setup.ts @@ -0,0 +1,4 @@ +import { expect } from 'vitest'; +import { createSnapshotSerializer } from '@scripts/vitest-config'; + +expect.addSnapshotSerializer(createSnapshotSerializer()); diff --git a/packages/builder/plugin-vue2/tests/tsconfig.json b/packages/builder/plugin-vue2/tests/tsconfig.json new file mode 100644 index 000000000000..787a882891b3 --- /dev/null +++ b/packages/builder/plugin-vue2/tests/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@modern-js/tsconfig/base", + "compilerOptions": { + "noEmit": true, + "declaration": false, + "jsx": "preserve", + "baseUrl": "./", + "isolatedModules": true, + "paths": { + "@rspack-builder/tests/*": ["../../builder-rspack-provider/tests/*"] + } + } +} diff --git a/packages/builder/plugin-vue2/tsconfig.json b/packages/builder/plugin-vue2/tsconfig.json new file mode 100644 index 000000000000..104083062e4b --- /dev/null +++ b/packages/builder/plugin-vue2/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "@modern-js/tsconfig/base", + "compilerOptions": { + "target": "ES2019", + "declaration": true, + "outDir": "./dist", + "jsx": "preserve", + "baseUrl": "./", + "isolatedModules": true, + "paths": {}, + "skipLibCheck": true + }, + "include": ["src"] +} diff --git a/packages/builder/plugin-vue2/vitest.config.ts b/packages/builder/plugin-vue2/vitest.config.ts new file mode 100644 index 000000000000..62b26b26b8e0 --- /dev/null +++ b/packages/builder/plugin-vue2/vitest.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'vitest/config'; +import { withTestPreset } from '@scripts/vitest-config'; + +const config = defineConfig({ + test: { + root: __dirname, + environment: 'node', + setupFiles: ['./tests/setup.ts'], + }, +}); + +export default withTestPreset(config); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ae1d452d3ad8..cedac5f1427d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -709,6 +709,49 @@ importers: specifier: ^5.88.1 version: 5.88.1(esbuild@0.17.19)(webpack-cli@5.1.4) + packages/builder/plugin-vue2: + dependencies: + '@modern-js/builder-shared': + specifier: workspace:* + version: link:../builder-shared + '@swc/helpers': + specifier: 0.5.1 + version: 0.5.1 + '@vue/babel-preset-jsx': + specifier: ^1.4.0 + version: 1.4.0(@babel/core@7.21.8) + vue-loader: + specifier: ^15.10.1 + version: 15.10.1(css-loader@6.7.1)(webpack@5.88.1) + devDependencies: + '@babel/core': + specifier: ^7.21.8 + version: 7.21.8 + '@modern-js/builder': + specifier: workspace:* + version: link:../builder + '@modern-js/builder-rspack-provider': + specifier: workspace:* + version: link:../builder-rspack-provider + '@modern-js/builder-webpack-provider': + specifier: workspace:* + version: link:../builder-webpack-provider + '@modern-js/utils': + specifier: workspace:* + version: link:../../toolkit/utils + '@scripts/build': + specifier: workspace:* + version: link:../../../scripts/build + '@scripts/vitest-config': + specifier: workspace:* + version: link:../../../scripts/vitest-config + typescript: + specifier: ^5 + version: 5.0.4 + webpack: + specifier: ^5.88.1 + version: 5.88.1(esbuild@0.17.19)(webpack-cli@5.1.4) + packages/cli/babel-preset-app: dependencies: '@babel/core': @@ -6046,6 +6089,9 @@ importers: '@modern-js/builder-plugin-vue': specifier: workspace:* version: link:../../../packages/builder/plugin-vue + '@modern-js/builder-plugin-vue2': + specifier: workspace:* + version: link:../../../packages/builder/plugin-vue2 '@modern-js/builder-rspack-provider': specifier: workspace:* version: link:../../../packages/builder/builder-rspack-provider @@ -6109,6 +6155,9 @@ importers: typescript: specifier: ^5 version: 5.0.4 + vue: + specifier: ^3.3.4 + version: 3.3.4 tests/e2e/builder/cases/builder-cli/builder-cli-webpack: devDependencies: @@ -6167,6 +6216,18 @@ importers: specifier: ^2 version: 2.29.3 + tests/e2e/builder/cases/vue: + dependencies: + vue: + specifier: ^3.3.4 + version: 3.3.4 + + tests/e2e/builder/cases/vue2: + dependencies: + vue: + specifier: ^2.7.14 + version: 2.7.14 + tests/e2e/garfish: dependencies: react: @@ -15754,6 +15815,10 @@ packages: sirv: 2.0.2 dev: true + /@vue/babel-helper-vue-jsx-merge-props@1.4.0: + resolution: {integrity: sha512-JkqXfCkUDp4PIlFdDQ0TdXoIejMtTHP67/pvxlgeY+u5k3LEdKuWZ3LK6xkxo52uDoABIVyRwqVkfLQJhk7VBA==} + dev: false + /@vue/babel-helper-vue-transform-on@1.0.2: resolution: {integrity: sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==} dev: false @@ -15775,6 +15840,101 @@ packages: - supports-color dev: false + /@vue/babel-plugin-transform-vue-jsx@1.4.0(@babel/core@7.21.8): + resolution: {integrity: sha512-Fmastxw4MMx0vlgLS4XBX0XiBbUFzoMGeVXuMV08wyOfXdikAFqBTuYPR0tlk+XskL19EzHc39SgjrPGY23JnA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/helper-module-imports': 7.21.4 + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.21.8) + '@vue/babel-helper-vue-jsx-merge-props': 1.4.0 + html-tags: 2.0.0 + lodash.kebabcase: 4.1.1 + svg-tags: 1.0.0 + dev: false + + /@vue/babel-preset-jsx@1.4.0(@babel/core@7.21.8): + resolution: {integrity: sha512-QmfRpssBOPZWL5xw7fOuHNifCQcNQC1PrOo/4fu6xlhlKJJKSA3HqX92Nvgyx8fqHZTUGMPHmFA+IDqwXlqkSA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + vue: '*' + peerDependenciesMeta: + vue: + optional: true + dependencies: + '@babel/core': 7.21.8 + '@vue/babel-helper-vue-jsx-merge-props': 1.4.0 + '@vue/babel-plugin-transform-vue-jsx': 1.4.0(@babel/core@7.21.8) + '@vue/babel-sugar-composition-api-inject-h': 1.4.0(@babel/core@7.21.8) + '@vue/babel-sugar-composition-api-render-instance': 1.4.0(@babel/core@7.21.8) + '@vue/babel-sugar-functional-vue': 1.4.0(@babel/core@7.21.8) + '@vue/babel-sugar-inject-h': 1.4.0(@babel/core@7.21.8) + '@vue/babel-sugar-v-model': 1.4.0(@babel/core@7.21.8) + '@vue/babel-sugar-v-on': 1.4.0(@babel/core@7.21.8) + dev: false + + /@vue/babel-sugar-composition-api-inject-h@1.4.0(@babel/core@7.21.8): + resolution: {integrity: sha512-VQq6zEddJHctnG4w3TfmlVp5FzDavUSut/DwR0xVoe/mJKXyMcsIibL42wPntozITEoY90aBV0/1d2KjxHU52g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.21.8) + dev: false + + /@vue/babel-sugar-composition-api-render-instance@1.4.0(@babel/core@7.21.8): + resolution: {integrity: sha512-6ZDAzcxvy7VcnCjNdHJ59mwK02ZFuP5CnucloidqlZwVQv5CQLijc3lGpR7MD3TWFi78J7+a8J56YxbCtHgT9Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.21.8) + dev: false + + /@vue/babel-sugar-functional-vue@1.4.0(@babel/core@7.21.8): + resolution: {integrity: sha512-lTEB4WUFNzYt2In6JsoF9sAYVTo84wC4e+PoZWSgM6FUtqRJz7wMylaEhSRgG71YF+wfLD6cc9nqVeXN2rwBvw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.21.8) + dev: false + + /@vue/babel-sugar-inject-h@1.4.0(@babel/core@7.21.8): + resolution: {integrity: sha512-muwWrPKli77uO2fFM7eA3G1lAGnERuSz2NgAxuOLzrsTlQl8W4G+wwbM4nB6iewlKbwKRae3nL03UaF5ffAPMA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.21.8) + dev: false + + /@vue/babel-sugar-v-model@1.4.0(@babel/core@7.21.8): + resolution: {integrity: sha512-0t4HGgXb7WHYLBciZzN5s0Hzqan4Ue+p/3FdQdcaHAb7s5D9WZFGoSxEZHrR1TFVZlAPu1bejTKGeAzaaG3NCQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.21.8) + '@vue/babel-helper-vue-jsx-merge-props': 1.4.0 + '@vue/babel-plugin-transform-vue-jsx': 1.4.0(@babel/core@7.21.8) + camelcase: 5.3.1 + html-tags: 2.0.0 + svg-tags: 1.0.0 + dev: false + + /@vue/babel-sugar-v-on@1.4.0(@babel/core@7.21.8): + resolution: {integrity: sha512-m+zud4wKLzSKgQrWwhqRObWzmTuyzl6vOP7024lrpeJM4x2UhQtRDLgYjXAw9xBXjCwS0pP9kXjg91F9ZNo9JA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.8 + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.21.8) + '@vue/babel-plugin-transform-vue-jsx': 1.4.0(@babel/core@7.21.8) + camelcase: 5.3.1 + dev: false + /@vue/compiler-core@3.3.4: resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} dependencies: @@ -15782,13 +15942,19 @@ packages: '@vue/shared': 3.3.4 estree-walker: 2.0.2 source-map-js: 1.0.2 - dev: false /@vue/compiler-dom@3.3.4: resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} dependencies: '@vue/compiler-core': 3.3.4 '@vue/shared': 3.3.4 + + /@vue/compiler-sfc@2.7.14: + resolution: {integrity: sha512-aNmNHyLPsw+sVvlQFQ2/8sjNuLtK54TC6cuKnVzAY93ks4ZBrvwQSnkkIh7bsbNhum5hJBS00wSDipQ937f5DA==} + dependencies: + '@babel/parser': 7.21.8 + postcss: 8.4.21 + source-map: 0.6.1 dev: false /@vue/compiler-sfc@3.3.4: @@ -15805,13 +15971,80 @@ packages: magic-string: 0.30.0 postcss: 8.4.21 source-map-js: 1.0.2 - dev: false /@vue/compiler-ssr@3.3.4: resolution: {integrity: sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==} dependencies: '@vue/compiler-dom': 3.3.4 '@vue/shared': 3.3.4 + + /@vue/component-compiler-utils@3.3.0: + resolution: {integrity: sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==} + dependencies: + consolidate: 0.15.1 + hash-sum: 1.0.2 + lru-cache: 4.1.5 + merge-source-map: 1.1.0 + postcss: 7.0.39 + postcss-selector-parser: 6.0.11 + source-map: 0.6.1 + vue-template-es2015-compiler: 1.9.1 + optionalDependencies: + prettier: 2.8.7 + transitivePeerDependencies: + - arc-templates + - atpl + - babel-core + - bracket-template + - coffee-script + - dot + - dust + - dustjs-helpers + - dustjs-linkedin + - eco + - ect + - ejs + - haml-coffee + - hamlet + - hamljs + - handlebars + - hogan.js + - htmling + - jade + - jazz + - jqtpl + - just + - liquid-node + - liquor + - lodash + - marko + - mote + - mustache + - nunjucks + - plates + - pug + - qejs + - ractive + - razor-tmpl + - react + - react-dom + - slm + - squirrelly + - swig + - swig-templates + - teacup + - templayed + - then-jade + - then-pug + - tinyliquid + - toffee + - twig + - twing + - underscore + - vash + - velocityjs + - walrus + - whiskers dev: false /@vue/reactivity-transform@3.3.4: @@ -15822,20 +16055,17 @@ packages: '@vue/shared': 3.3.4 estree-walker: 2.0.2 magic-string: 0.30.0 - dev: false /@vue/reactivity@3.3.4: resolution: {integrity: sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==} dependencies: '@vue/shared': 3.3.4 - dev: false /@vue/runtime-core@3.3.4: resolution: {integrity: sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==} dependencies: '@vue/reactivity': 3.3.4 '@vue/shared': 3.3.4 - dev: false /@vue/runtime-dom@3.3.4: resolution: {integrity: sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==} @@ -15843,7 +16073,6 @@ packages: '@vue/runtime-core': 3.3.4 '@vue/shared': 3.3.4 csstype: 3.1.2 - dev: false /@vue/server-renderer@3.3.4(vue@3.3.4): resolution: {integrity: sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==} @@ -15853,11 +16082,9 @@ packages: '@vue/compiler-ssr': 3.3.4 '@vue/shared': 3.3.4 vue: 3.3.4 - dev: false /@vue/shared@3.3.4: resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} - dev: false /@web3-storage/multipart-parser@1.0.0: resolution: {integrity: sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==} @@ -18331,6 +18558,175 @@ packages: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} dev: false + /consolidate@0.15.1: + resolution: {integrity: sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==} + engines: {node: '>= 0.10.0'} + deprecated: Please upgrade to consolidate v1.0.0+ as it has been modernized with several long-awaited fixes implemented. Maintenance is supported by Forward Email at https://forwardemail.net ; follow/watch https://github.com/ladjs/consolidate for updates and release changelog + peerDependencies: + arc-templates: ^0.5.3 + atpl: '>=0.7.6' + babel-core: ^6.26.3 + bracket-template: ^1.1.5 + coffee-script: ^1.12.7 + dot: ^1.1.3 + dust: ^0.3.0 + dustjs-helpers: ^1.7.4 + dustjs-linkedin: ^2.7.5 + eco: ^1.1.0-rc-3 + ect: ^0.5.9 + ejs: ^3.1.5 + haml-coffee: ^1.14.1 + hamlet: ^0.3.3 + hamljs: ^0.6.2 + handlebars: ^4.7.6 + hogan.js: ^3.0.2 + htmling: ^0.0.8 + jade: ^1.11.0 + jazz: ^0.0.18 + jqtpl: ~1.1.0 + just: ^0.1.8 + liquid-node: ^3.0.1 + liquor: ^0.0.5 + lodash: ^4.17.20 + marko: ^3.14.4 + mote: ^0.2.0 + mustache: ^3.0.0 + nunjucks: ^3.2.2 + plates: ~0.4.11 + pug: ^3.0.0 + qejs: ^3.0.5 + ractive: ^1.3.12 + razor-tmpl: ^1.3.1 + react: ^16.13.1 + react-dom: ^16.13.1 + slm: ^2.0.0 + squirrelly: ^5.1.0 + swig: ^1.4.2 + swig-templates: ^2.0.3 + teacup: ^2.0.0 + templayed: '>=0.2.3' + then-jade: '*' + then-pug: '*' + tinyliquid: ^0.2.34 + toffee: ^0.3.6 + twig: ^1.15.2 + twing: ^5.0.2 + underscore: ^1.11.0 + vash: ^0.13.0 + velocityjs: ^2.0.1 + walrus: ^0.10.1 + whiskers: ^0.4.0 + peerDependenciesMeta: + arc-templates: + optional: true + atpl: + optional: true + babel-core: + optional: true + bracket-template: + optional: true + coffee-script: + optional: true + dot: + optional: true + dust: + optional: true + dustjs-helpers: + optional: true + dustjs-linkedin: + optional: true + eco: + optional: true + ect: + optional: true + ejs: + optional: true + haml-coffee: + optional: true + hamlet: + optional: true + hamljs: + optional: true + handlebars: + optional: true + hogan.js: + optional: true + htmling: + optional: true + jade: + optional: true + jazz: + optional: true + jqtpl: + optional: true + just: + optional: true + liquid-node: + optional: true + liquor: + optional: true + lodash: + optional: true + marko: + optional: true + mote: + optional: true + mustache: + optional: true + nunjucks: + optional: true + plates: + optional: true + pug: + optional: true + qejs: + optional: true + ractive: + optional: true + razor-tmpl: + optional: true + react: + optional: true + react-dom: + optional: true + slm: + optional: true + squirrelly: + optional: true + swig: + optional: true + swig-templates: + optional: true + teacup: + optional: true + templayed: + optional: true + then-jade: + optional: true + then-pug: + optional: true + tinyliquid: + optional: true + toffee: + optional: true + twig: + optional: true + twing: + optional: true + underscore: + optional: true + vash: + optional: true + velocityjs: + optional: true + walrus: + optional: true + whiskers: + optional: true + dependencies: + bluebird: 3.7.2 + dev: false + /constantinople@4.0.1: resolution: {integrity: sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==} dependencies: @@ -18743,7 +19139,6 @@ packages: postcss-value-parser: 4.2.0 semver: 7.3.7 webpack: 5.88.1(esbuild@0.17.19)(webpack-cli@5.1.4) - dev: true /css-minimizer-webpack-plugin@5.0.0(esbuild@0.17.19)(webpack@5.88.1): resolution: {integrity: sha512-1wZ/PYvg+ZKwi5FX6YrvbB31jMAdurS+CmRQLwWCVSlfzJC85l/a6RVICqUHFa+jXyhilfnCyjafzJGbmz5tcA==} @@ -22143,6 +22538,10 @@ packages: safe-buffer: 5.2.1 dev: false + /hash-sum@1.0.2: + resolution: {integrity: sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==} + dev: false + /hash-sum@2.0.0: resolution: {integrity: sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==} dev: false @@ -22474,6 +22873,11 @@ packages: terser: 5.17.3 dev: false + /html-tags@2.0.0: + resolution: {integrity: sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==} + engines: {node: '>=4'} + dev: false + /html-tags@3.2.0: resolution: {integrity: sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==} engines: {node: '>=8'} @@ -25346,6 +25750,12 @@ packages: /merge-descriptors@1.0.1: resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + /merge-source-map@1.1.0: + resolution: {integrity: sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==} + dependencies: + source-map: 0.6.1 + dev: false + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -33018,6 +33428,89 @@ packages: resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} dev: false + /vue-hot-reload-api@2.3.4: + resolution: {integrity: sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==} + dev: false + + /vue-loader@15.10.1(css-loader@6.7.1)(webpack@5.88.1): + resolution: {integrity: sha512-SaPHK1A01VrNthlix6h1hq4uJu7S/z0kdLUb6klubo738NeQoLbS6V9/d8Pv19tU0XdQKju3D1HSKuI8wJ5wMA==} + peerDependencies: + '@vue/compiler-sfc': ^3.0.8 + cache-loader: '*' + css-loader: '*' + vue-template-compiler: '*' + webpack: ^3.0.0 || ^4.1.0 || ^5.0.0-0 + peerDependenciesMeta: + '@vue/compiler-sfc': + optional: true + cache-loader: + optional: true + vue-template-compiler: + optional: true + dependencies: + '@vue/component-compiler-utils': 3.3.0 + css-loader: 6.7.1(webpack@5.88.1) + hash-sum: 1.0.2 + loader-utils: 1.4.0 + vue-hot-reload-api: 2.3.4 + vue-style-loader: 4.1.3 + webpack: 5.88.1(esbuild@0.17.19)(webpack-cli@5.1.4) + transitivePeerDependencies: + - arc-templates + - atpl + - babel-core + - bracket-template + - coffee-script + - dot + - dust + - dustjs-helpers + - dustjs-linkedin + - eco + - ect + - ejs + - haml-coffee + - hamlet + - hamljs + - handlebars + - hogan.js + - htmling + - jade + - jazz + - jqtpl + - just + - liquid-node + - liquor + - lodash + - marko + - mote + - mustache + - nunjucks + - plates + - pug + - qejs + - ractive + - razor-tmpl + - react + - react-dom + - slm + - squirrelly + - swig + - swig-templates + - teacup + - templayed + - then-jade + - then-pug + - tinyliquid + - toffee + - twig + - twing + - underscore + - vash + - velocityjs + - walrus + - whiskers + dev: false + /vue-loader@17.2.2(webpack@5.88.1): resolution: {integrity: sha512-aqNvKJvnz2A/6VWeJZodAo8XLoAlVwBv+2Z6dama+LHsAF+P/xijQ+OfWrxIs0wcGSJduvdzvTuATzXbNKkpiw==} peerDependencies: @@ -33036,6 +33529,13 @@ packages: webpack: 5.88.1(esbuild@0.17.19)(webpack-cli@5.1.4) dev: false + /vue-style-loader@4.1.3: + resolution: {integrity: sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==} + dependencies: + hash-sum: 1.0.2 + loader-utils: 1.4.0 + dev: false + /vue-template-compiler@2.7.14: resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==} requiresBuild: true @@ -33045,6 +33545,17 @@ packages: dev: false optional: true + /vue-template-es2015-compiler@1.9.1: + resolution: {integrity: sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==} + dev: false + + /vue@2.7.14: + resolution: {integrity: sha512-b2qkFyOM0kwqWFuQmgd4o+uHGU7T+2z3T+WQp8UBjADfEv2n4FEMffzBmCKNP0IGzOEEfYjvtcC62xaSKeQDrQ==} + dependencies: + '@vue/compiler-sfc': 2.7.14 + csstype: 3.1.2 + dev: false + /vue@3.3.4: resolution: {integrity: sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==} dependencies: @@ -33053,7 +33564,6 @@ packages: '@vue/runtime-dom': 3.3.4 '@vue/server-renderer': 3.3.4(vue@3.3.4) '@vue/shared': 3.3.4 - dev: false /w3c-xmlserializer@4.0.0: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} diff --git a/tests/e2e/builder/cases/builder-cli/builder-cli-vue/package.json b/tests/e2e/builder/cases/builder-cli/builder-cli-vue/package.json index 8577ebb8bb08..6d2654288f25 100644 --- a/tests/e2e/builder/cases/builder-cli/builder-cli-vue/package.json +++ b/tests/e2e/builder/cases/builder-cli/builder-cli-vue/package.json @@ -17,7 +17,8 @@ "devDependencies": { "@modern-js/builder-cli": "workspace:*", "@modern-js/builder-rspack-provider": "workspace:*", + "@types/node": "^14", "typescript": "^5", - "@types/node": "^14" + "vue": "^3.3.4" } } diff --git a/tests/e2e/builder/cases/vue/package.json b/tests/e2e/builder/cases/vue/package.json new file mode 100644 index 000000000000..26b75112dab2 --- /dev/null +++ b/tests/e2e/builder/cases/vue/package.json @@ -0,0 +1,8 @@ +{ + "private": true, + "name": "@e2e/builder-vue3", + "version": "1.0.0", + "dependencies": { + "vue": "^3.3.4" + } +} diff --git a/tests/e2e/builder/cases/vue2/index.test.ts b/tests/e2e/builder/cases/vue2/index.test.ts new file mode 100644 index 000000000000..15d6139ade39 --- /dev/null +++ b/tests/e2e/builder/cases/vue2/index.test.ts @@ -0,0 +1,119 @@ +import { join } from 'path'; +import { expect, test } from '@modern-js/e2e/playwright'; +import { build, getHrefByEntryName } from '@scripts/shared'; +import { builderPluginVue2 } from '@modern-js/builder-plugin-vue2'; + +test('should build basic Vue sfc correctly', async ({ page }) => { + const root = join(__dirname, 'sfc-basic'); + + const builder = await build({ + cwd: root, + entry: { + main: join(root, 'src/index.js'), + }, + runServer: true, + plugins: [builderPluginVue2()], + }); + + await page.goto(getHrefByEntryName('main', builder.port)); + await expect( + page.evaluate(`document.querySelector('#button1').innerHTML`), + ).resolves.toBe('A: 0'); + await expect( + page.evaluate(`document.querySelector('#button2').innerHTML`), + ).resolves.toBe('B: 0'); + + builder.close(); +}); + +test('should build basic Vue jsx correctly', async ({ page }) => { + const root = join(__dirname, 'jsx-basic'); + + const builder = await build({ + cwd: root, + entry: { + main: join(root, 'src/index.js'), + }, + runServer: true, + plugins: [builderPluginVue2()], + }); + + await page.goto(getHrefByEntryName('main', builder.port)); + + await expect( + page.evaluate(`document.querySelector('#button1').innerHTML`), + ).resolves.toBe('A: 0'); + + builder.close(); +}); + +test('should build Vue sfc with lang="ts" correctly', async ({ page }) => { + const root = join(__dirname, 'sfc-lang-ts'); + + const builder = await build({ + cwd: root, + entry: { + main: join(root, 'src/index.js'), + }, + runServer: true, + plugins: [builderPluginVue2()], + }); + + await page.goto(getHrefByEntryName('main', builder.port)); + + await expect( + page.evaluate(`document.querySelector('#button').innerHTML`), + ).resolves.toContain('count: 0 foo: bar'); + + builder.close(); +}); + +test('should build Vue sfc with lang="jsx" correctly', async ({ page }) => { + const root = join(__dirname, 'sfc-lang-jsx'); + + const builder = await build({ + cwd: root, + entry: { + main: join(root, 'src/index.js'), + }, + runServer: true, + plugins: [builderPluginVue2()], + }); + + await page.goto(getHrefByEntryName('main', builder.port)); + + await expect( + page.evaluate(`document.querySelector('#button').innerHTML`), + ).resolves.toBe('0'); + + await expect( + page.evaluate(`document.querySelector('#foo').innerHTML`), + ).resolves.toBe('Foo'); + + builder.close(); +}); + +test('should build Vue sfc with lang="tsx" correctly', async ({ page }) => { + const root = join(__dirname, 'sfc-lang-tsx'); + + const builder = await build({ + cwd: root, + entry: { + main: join(root, 'src/index.js'), + }, + runServer: true, + plugins: [builderPluginVue2()], + }); + + await page.goto(getHrefByEntryName('main', builder.port)); + + await expect( + page.evaluate(`document.querySelector('#button').innerHTML`), + ).resolves.toBe('0'); + + await expect( + page.evaluate(`document.querySelector('#foo').innerHTML`), + ).resolves.toBe('Foo'); + + builder.close(); +}); diff --git a/tests/e2e/builder/cases/vue2/jsx-basic/src/A.jsx b/tests/e2e/builder/cases/vue2/jsx-basic/src/A.jsx new file mode 100644 index 000000000000..a43c0f589be9 --- /dev/null +++ b/tests/e2e/builder/cases/vue2/jsx-basic/src/A.jsx @@ -0,0 +1,19 @@ +import { defineComponent } from 'vue'; + +export default defineComponent({ + name: 'Test', + + data() { + return { + count: 0, + }; + }, + + render() { + return ( + + ); + }, +}); diff --git a/tests/e2e/builder/cases/vue2/jsx-basic/src/index.js b/tests/e2e/builder/cases/vue2/jsx-basic/src/index.js new file mode 100644 index 000000000000..3e33bf75f523 --- /dev/null +++ b/tests/e2e/builder/cases/vue2/jsx-basic/src/index.js @@ -0,0 +1,8 @@ +import Vue from 'vue'; +import A from './A'; + +// eslint-disable-next-line no-new +new Vue({ + el: '#root', + render: h => h(A), +}); diff --git a/tests/e2e/builder/cases/vue2/package.json b/tests/e2e/builder/cases/vue2/package.json new file mode 100644 index 000000000000..414a22950795 --- /dev/null +++ b/tests/e2e/builder/cases/vue2/package.json @@ -0,0 +1,8 @@ +{ + "private": true, + "name": "@e2e/builder-vue2", + "version": "1.0.0", + "dependencies": { + "vue": "^2.7.14" + } +} diff --git a/tests/e2e/builder/cases/vue2/sfc-basic/src/A.vue b/tests/e2e/builder/cases/vue2/sfc-basic/src/A.vue new file mode 100644 index 000000000000..54f53ba7aa53 --- /dev/null +++ b/tests/e2e/builder/cases/vue2/sfc-basic/src/A.vue @@ -0,0 +1,25 @@ + + + diff --git a/tests/e2e/builder/cases/vue2/sfc-basic/src/B.vue b/tests/e2e/builder/cases/vue2/sfc-basic/src/B.vue new file mode 100644 index 000000000000..37396202aad9 --- /dev/null +++ b/tests/e2e/builder/cases/vue2/sfc-basic/src/B.vue @@ -0,0 +1,14 @@ + + + diff --git a/tests/e2e/builder/cases/vue2/sfc-basic/src/index.js b/tests/e2e/builder/cases/vue2/sfc-basic/src/index.js new file mode 100644 index 000000000000..f6536e93cab6 --- /dev/null +++ b/tests/e2e/builder/cases/vue2/sfc-basic/src/index.js @@ -0,0 +1,8 @@ +import Vue from 'vue'; +import A from './A.vue'; + +// eslint-disable-next-line no-new +new Vue({ + el: '#root', + render: h => h(A), +}); diff --git a/tests/e2e/builder/cases/vue2/sfc-lang-jsx/src/App.vue b/tests/e2e/builder/cases/vue2/sfc-lang-jsx/src/App.vue new file mode 100644 index 000000000000..7f9fc425b877 --- /dev/null +++ b/tests/e2e/builder/cases/vue2/sfc-lang-jsx/src/App.vue @@ -0,0 +1,27 @@ + + + diff --git a/tests/e2e/builder/cases/vue2/sfc-lang-jsx/src/index.js b/tests/e2e/builder/cases/vue2/sfc-lang-jsx/src/index.js new file mode 100644 index 000000000000..625f1c8c3b95 --- /dev/null +++ b/tests/e2e/builder/cases/vue2/sfc-lang-jsx/src/index.js @@ -0,0 +1,8 @@ +import Vue from 'vue'; +import App from './App.vue'; + +// eslint-disable-next-line no-new +new Vue({ + el: '#root', + render: h => h(App), +}); diff --git a/tests/e2e/builder/cases/vue2/sfc-lang-ts/src/App.vue b/tests/e2e/builder/cases/vue2/sfc-lang-ts/src/App.vue new file mode 100644 index 000000000000..06e673427a0b --- /dev/null +++ b/tests/e2e/builder/cases/vue2/sfc-lang-ts/src/App.vue @@ -0,0 +1,22 @@ + + + diff --git a/tests/e2e/builder/cases/vue2/sfc-lang-ts/src/index.js b/tests/e2e/builder/cases/vue2/sfc-lang-ts/src/index.js new file mode 100644 index 000000000000..579a575168c8 --- /dev/null +++ b/tests/e2e/builder/cases/vue2/sfc-lang-ts/src/index.js @@ -0,0 +1,8 @@ +import Vue from 'vue'; +import App from './App.vue'; + +// eslint-disable-next-line no-new +new Vue({ + el: '#root', + render: h => h(App, { props: { foo: 'bar' } }), +}); diff --git a/tests/e2e/builder/cases/vue2/sfc-lang-tsx/src/App.vue b/tests/e2e/builder/cases/vue2/sfc-lang-tsx/src/App.vue new file mode 100644 index 000000000000..a983a1402f34 --- /dev/null +++ b/tests/e2e/builder/cases/vue2/sfc-lang-tsx/src/App.vue @@ -0,0 +1,27 @@ + + + diff --git a/tests/e2e/builder/cases/vue2/sfc-lang-tsx/src/index.js b/tests/e2e/builder/cases/vue2/sfc-lang-tsx/src/index.js new file mode 100644 index 000000000000..625f1c8c3b95 --- /dev/null +++ b/tests/e2e/builder/cases/vue2/sfc-lang-tsx/src/index.js @@ -0,0 +1,8 @@ +import Vue from 'vue'; +import App from './App.vue'; + +// eslint-disable-next-line no-new +new Vue({ + el: '#root', + render: h => h(App), +}); diff --git a/tests/e2e/builder/package.json b/tests/e2e/builder/package.json index de83c3c12205..be226102809c 100644 --- a/tests/e2e/builder/package.json +++ b/tests/e2e/builder/package.json @@ -20,6 +20,7 @@ "@modern-js/builder-plugin-stylus": "workspace:*", "@modern-js/builder-plugin-swc": "workspace:*", "@modern-js/builder-plugin-vue": "workspace:*", + "@modern-js/builder-plugin-vue2": "workspace:*", "@modern-js/builder-rspack-provider": "workspace:*", "@modern-js/builder-shared": "workspace:*", "@modern-js/builder-webpack-provider": "workspace:*",