├── .gitignore
├── LICENSE
├── README.md
├── package.json
├── packages
├── app1
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── assets
│ │ │ └── logo.png
│ │ ├── components
│ │ │ └── test.vue
│ │ ├── main.js
│ │ ├── pages
│ │ │ └── App.vue
│ │ ├── shims-vue.d.ts
│ │ └── store
│ │ │ ├── Actions.js
│ │ │ ├── Getters.js
│ │ │ ├── Mutations.js
│ │ │ ├── State.js
│ │ │ └── index.js
│ ├── webpack.dev.config.js
│ └── webpack.prod.config.js
├── app2
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── assets
│ │ │ └── logo.png
│ │ ├── components
│ │ │ └── test.vue
│ │ ├── main.js
│ │ ├── pages
│ │ │ └── App.vue
│ │ ├── shims-vue.d.ts
│ │ └── store
│ │ │ ├── Actions.js
│ │ │ ├── Getters.js
│ │ │ ├── Mutations.js
│ │ │ ├── State.js
│ │ │ └── index.js
│ ├── webpack.dev.config.js
│ └── webpack.prod.config.js
└── main
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── src
│ ├── api
│ │ └── login.js
│ ├── assets
│ │ ├── back.png
│ │ └── logo.png
│ ├── layout
│ │ └── Header.vue
│ ├── main.js
│ ├── pages
│ │ ├── App.vue
│ │ ├── Home.vue
│ │ └── Login.vue
│ ├── router
│ │ └── index.js
│ ├── shims-vue.d.ts
│ ├── store
│ │ ├── Actions.js
│ │ ├── Getters.js
│ │ ├── Mutations.js
│ │ ├── State.js
│ │ └── index.js
│ └── utils
│ │ ├── index.js
│ │ └── request.js
│ ├── webpack.dev.config.js
│ └── webpack.prod.config.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | dist/
3 | package-lock.json
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Cody Mathisen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | # 使用 webpack5 wsrun 构建多页面应用
4 |
5 | 1.安装 yarn
6 | 2.yarn install
7 | 3.依赖暂时存放在 main 工程 其他子工程共享
8 | 4.cd packages/main yarn install
9 | 5.工程使用 vue3 vuex4 vue-router4 ant-design-vue2.x webpack5 等
10 |
11 | # 启动
12 |
13 | yarn serve / yarn start
14 |
15 | # 构建
16 |
17 | yarn build
18 |
19 | # TODO 子工程模板放到私库,创建子工程使用命令行创建
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webpack5-module-federation-beta",
3 | "private": true,
4 | "author": "Austion Wong",
5 | "scripts": {
6 | "build": "yarn workspaces run build",
7 | "serve": "wsrun --parallel serve",
8 | "start": "concurrently \"wsrun --parallel start\" \"wsrun --parallel serve\""
9 | },
10 | "workspaces": [
11 | "packages/*"
12 | ],
13 | "devDependencies": {
14 | "concurrently": "^5.1.0",
15 | "wsrun": "^5.2.0"
16 | },
17 | "dependencies": {}
18 | }
--------------------------------------------------------------------------------
/packages/app1/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | dist/
3 | package-lock.json
--------------------------------------------------------------------------------
/packages/app1/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/packages/app1/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "yj-nc",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "serve": "webpack-dev-server --config webpack.dev.config.js --env.mode development --watch --profile",
9 | "build": "webpack --config webpack.prod.config.js --env.mode production"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "@babel/core": "^7.12.9",
16 | "@babel/plugin-transform-runtime": "^7.12.1",
17 | "@babel/preset-env": "^7.12.7",
18 | "@vue/compiler-sfc": "^3.0.2",
19 | "babel-loader": "^8.2.1",
20 | "babel-plugin-import": "^1.13.3",
21 | "clean-webpack-plugin": "^3.0.0",
22 | "copy-webpack-plugin": "^6.3.2",
23 | "css-loader": "^5.0.1",
24 | "html-webpack-plugin": "^4.5.0",
25 | "less": "^3.12.2",
26 | "less-loader": "^7.1.0",
27 | "mini-css-extract-plugin": "^1.3.1",
28 | "style-loader": "^2.0.0",
29 | "vue-loader": "^16.0.0-rc.1",
30 | "webpack": "^5.6.0",
31 | "webpack-cli": "^3.3.12",
32 | "webpack-dev-server": "^3.11.0"
33 | },
34 | "dependencies": {
35 | "@babel/runtime": "^7.12.5",
36 | "ant-design-vue": "^2.0.0-beta.15",
37 | "serve": "^11.3.2",
38 | "vue": "^3.0.2",
39 | "vuex": "^4.0.0-rc.1"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/packages/app1/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/120397474/webpack5-moduleFederation/0549420becefbb50820522e8b332e26b5966c3df/packages/app1/src/assets/logo.png
--------------------------------------------------------------------------------
/packages/app1/src/components/test.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
我是App1的组件
4 | 我来自App1
5 | 真的,我真的来自App1
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/packages/app1/src/main.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description: 开发模式,vue需要完整入口文件
3 | * @Author: Austin wong
4 | * @Date: 2020-11-09 00:56:37
5 | */
6 | import { createApp } from "vue";
7 | import box from "./pages/App.vue";
8 | import store from './store';
9 | import 'ant-design-vue/dist/antd.less';
10 |
11 | const app = createApp(box);
12 | app.use(store).mount('#app');
--------------------------------------------------------------------------------
/packages/app1/src/pages/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
我是App1的入口文件
4 | {{ counter }}
5 |
6 |
7 |
8 |
9 |
30 |
31 |
--------------------------------------------------------------------------------
/packages/app1/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: YourName
3 | * @Date: 2021-04-16 18:13:16
4 | * @LastEditTime: 2022-07-26 22:06:12
5 | * @LastEditors: YourName
6 | * @Description: 文件功能描述
7 | * @FilePath: \yunjian-form\packages\app1\src\shims-vue.d.ts
8 | */
9 |
10 | declare module '*.vue' {
11 | import Vue from 'vue';
12 | export default Vue;
13 | }
14 |
15 | declare module "vue/types/vue" {
16 | interface Vue {
17 | $http: any;
18 | $Message: any;
19 | $Modal: any;
20 | }
21 | }
--------------------------------------------------------------------------------
/packages/app1/src/store/Actions.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description:
3 | * @Author: Gouxinyu
4 | * @Date: 2020-08-03 23:25:36
5 | */
6 | export default {
7 |
8 | }
--------------------------------------------------------------------------------
/packages/app1/src/store/Getters.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description:
3 | * @Author: Gouxinyu
4 | * @Date: 2020-08-03 23:26:11
5 | */
6 | export default {
7 | }
--------------------------------------------------------------------------------
/packages/app1/src/store/Mutations.js:
--------------------------------------------------------------------------------
1 | const mutations = {
2 | addCount(state) {
3 | state.counter += 1;
4 | }
5 | }
6 |
7 | export default mutations;
--------------------------------------------------------------------------------
/packages/app1/src/store/State.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | counter: 0
3 | }
4 |
5 | export default state;
--------------------------------------------------------------------------------
/packages/app1/src/store/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description:
3 | * @Author: Gouxinyu
4 | * @Date: 2020-08-02 23:04:30
5 | */
6 |
7 | import { createStore } from 'vuex';
8 | import state from './State';
9 | import mutations from './Mutations';
10 | import actions from './Actions';
11 | import getters from './Getters';
12 |
13 | const store = createStore({
14 | state,
15 | mutations,
16 | actions,
17 | getters
18 | })
19 |
20 | export default store;
--------------------------------------------------------------------------------
/packages/app1/webpack.dev.config.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description: webpack5配置
3 | * @Author: austin wong
4 | * @Date: 2020-11-09 00:27:35
5 | */
6 | const path = require('path');
7 | const { HotModuleReplacementPlugin, IgnorePlugin } = require('webpack');
8 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
9 | const HtmlWebpackPlugin = require('html-webpack-plugin');
10 | const { VueLoaderPlugin } = require('vue-loader');
11 | const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
12 |
13 | const config = {
14 | mode: 'development',
15 | entry: './src/main.js',
16 | output: {
17 | filename: 'index.js',
18 | path: path.resolve(__dirname, 'dist')
19 | },
20 | devServer: {
21 | contentBase: false,
22 | // publicPath: './dist',
23 | hot: true,
24 | port: 3001,
25 | open: false,
26 | // hotOnly: true,
27 | compress: true,
28 | overlay: true,
29 | disableHostCheck: true, // 新增该配置项
30 | },
31 | watchOptions: {
32 | ignored: /node_modules/
33 | },
34 | plugins: [
35 | new CleanWebpackPlugin(),
36 | new HtmlWebpackPlugin({
37 | title: 'Hot Module Replacement',
38 | template: 'index.html'
39 | }),
40 | new IgnorePlugin(/^\.\/locale$/, /moment$/),
41 | new HotModuleReplacementPlugin(),
42 | new VueLoaderPlugin(),
43 | new ModuleFederationPlugin({
44 | name: "app1",
45 | filename: "remoteEntry.js",
46 | remotes: {
47 | 'main': "main@http://localhost:3000/remoteEntry.js"
48 | },
49 | exposes: {
50 | './Test': "./src/components/test.vue"
51 | },
52 | shared: []
53 | })
54 | ],
55 | module: {
56 | rules: [
57 | // babel使用runtime,避免将不需要的代码注入
58 | {
59 | test: /\.js$/,
60 | exclude: /node_modules/,
61 | use: [{
62 | loader: 'babel-loader',
63 | options: {
64 | // cacheDirectory: true,
65 | presets: ['@babel/preset-env'],
66 | plugins: [
67 | '@babel/plugin-transform-runtime', ['import', {
68 | "libraryName": "antd",
69 | "style": true, // or 'css'
70 | }, 'antd']
71 | ]
72 | }
73 | }],
74 | },
75 | {
76 | test: /\.vue$/,
77 | loader: 'vue-loader'
78 | },
79 | {
80 | test: /\.css$/,
81 | use: ['style-loader', 'css-loader']
82 | },
83 | {
84 | test: /\.less$/,
85 | use: ['style-loader', 'css-loader',
86 | {
87 | loader: 'less-loader',
88 | options: {
89 | lessOptions: {
90 | modifyVars: {
91 | 'primary-color': '#4608e2',
92 | 'link-color': '#4608e2',
93 | 'border-radius-base': '20px',
94 | },
95 | javascriptEnabled: true,
96 | }
97 | }
98 | }
99 | ],
100 | }
101 | ]
102 | },
103 | resolve: {
104 | extensions: ['.js']
105 | },
106 | };
107 |
108 |
109 | module.exports = (env) => {
110 | console.log(`当前执行${env.mode}模式`);
111 |
112 | return config;
113 | }
--------------------------------------------------------------------------------
/packages/app1/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description: webpack5配置
3 | * @Author: austin wong
4 | * @Date: 2021-04-16 13:26:28
5 | */
6 | const path = require('path');
7 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
8 | const HtmlWebpackPlugin = require('html-webpack-plugin');
9 | const CopyWebpackPlugin = require('copy-webpack-plugin');
10 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
11 | const { VueLoaderPlugin } = require('vue-loader');
12 | const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
13 |
14 | const config = {
15 | mode: 'production',
16 | entry: './src/main.js',
17 | output: {
18 | filename: 'index.js',
19 | path: path.resolve(__dirname, 'dist')
20 | },
21 | plugins: [
22 | new CleanWebpackPlugin(),
23 | new HtmlWebpackPlugin({
24 | title: 'Hot Module Replacement',
25 | template: 'index.html'
26 | }),
27 | new CopyWebpackPlugin({
28 | patterns: [
29 | {
30 | from: 'src/assets',
31 | to: 'assets'
32 | },
33 | ]
34 | }),
35 | new MiniCssExtractPlugin({
36 | filename: './index.css'
37 | }),
38 | new VueLoaderPlugin(),
39 | new ModuleFederationPlugin({
40 | name: "app1",
41 | // library: { type: "var", name: "yj-nc" },
42 | filename: "remoteEntry.js",
43 | remotes: {
44 | 'main': "main@http://localhost:3000/remoteEntry.js"
45 | },
46 | exposes: {
47 | './Test': "./src/components/test.vue"
48 | },
49 | shared: []
50 | })
51 | ],
52 | module: {
53 | rules: [
54 | // babel使用runtime,避免将不需要的代码注入
55 | {
56 | test: /\.js$/,
57 | exclude: /node_modules/,
58 | use: [{
59 | loader: 'babel-loader',
60 | options: {
61 | cacheDirectory: true,
62 | presets: ['@babel/preset-env'],
63 | plugins: [
64 | ['import', {
65 | "libraryName": "antd",
66 | "style": true, // or 'css'
67 | }, 'antd']
68 | ]
69 | }
70 | }],
71 | },
72 | {
73 | test: /\.vue$/,
74 | use: ['vue-loader']
75 | },
76 | {
77 | test: /\.css$/,
78 | use: [MiniCssExtractPlugin.loader, 'css-loader']
79 | },
80 | {
81 | test: /\.less$/,
82 | use: [MiniCssExtractPlugin.loader, 'css-loader', {
83 | loader: 'less-loader',
84 | options: {
85 | lessOptions: {
86 | modifyVars: {
87 | 'primary-color': '#4608e2',
88 | 'link-color': '#4608e2',
89 | 'border-radius-base': '20px',
90 | },
91 | javascriptEnabled: true,
92 | }
93 | }
94 | }]
95 | }
96 | ]
97 | },
98 | resolve: {
99 | extensions: ['.js']
100 | },
101 | };
102 |
103 | module.exports = (env) => {
104 | console.log(`当前执行${env.mode}模式`);
105 | // 如果是开发模式,
106 |
107 | return config;
108 | }
--------------------------------------------------------------------------------
/packages/app2/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | dist/
3 | package-lock.json
--------------------------------------------------------------------------------
/packages/app2/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/packages/app2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app2",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "serve": "webpack-dev-server --config webpack.dev.config.js --env.mode development --watch --profile",
9 | "build": "webpack --config webpack.prod.config.js --env.mode production"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "@babel/core": "^7.12.9",
16 | "@babel/plugin-transform-runtime": "^7.12.1",
17 | "@babel/preset-env": "^7.12.7",
18 | "@vue/compiler-sfc": "^3.0.2",
19 | "babel-loader": "^8.2.1",
20 | "babel-plugin-import": "^1.13.3",
21 | "clean-webpack-plugin": "^3.0.0",
22 | "copy-webpack-plugin": "^6.3.2",
23 | "css-loader": "^5.0.1",
24 | "html-webpack-plugin": "^4.5.0",
25 | "less": "^3.12.2",
26 | "less-loader": "^7.1.0",
27 | "mini-css-extract-plugin": "^1.3.1",
28 | "style-loader": "^2.0.0",
29 | "vue-loader": "^16.0.0-rc.1",
30 | "webpack": "^5.6.0",
31 | "webpack-cli": "^3.3.12",
32 | "webpack-dev-server": "^3.11.0"
33 | },
34 | "dependencies": {
35 | "@babel/runtime": "^7.12.5",
36 | "ant-design-vue": "^2.0.0-beta.15",
37 | "serve": "^11.3.2",
38 | "vue": "^3.0.2",
39 | "vuex": "^4.0.0-rc.1"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/packages/app2/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/120397474/webpack5-moduleFederation/0549420becefbb50820522e8b332e26b5966c3df/packages/app2/src/assets/logo.png
--------------------------------------------------------------------------------
/packages/app2/src/components/test.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
我是App1的组件
4 | 我来自App1
5 | 真的,我真的来自App1
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/packages/app2/src/main.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description: 开发模式,vue需要完整入口文件
3 | * @Author: Austin wong
4 | * @Date: 2020-11-09 00:56:37
5 | */
6 | import { createApp } from "vue";
7 | import box from "./pages/App.vue";
8 | import store from './store';
9 | import 'ant-design-vue/dist/antd.less';
10 |
11 | const app = createApp(box);
12 | app.use(store).mount('#app');
--------------------------------------------------------------------------------
/packages/app2/src/pages/App.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 | --------------------
12 |
我是App2的入口文件
13 |
14 |
15 |
16 |
17 |
39 |
40 |
--------------------------------------------------------------------------------
/packages/app2/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * @description:
3 | * @Author: Gouxinyu
4 | * @Date: 2020-11-13 15:34:03
5 | */
6 | declare module '*.vue' {
7 | import Vue from 'vue';
8 | export default Vue;
9 | }
10 |
11 | declare module "vue/types/vue" {
12 | interface Vue {
13 | $http: any;
14 | $Message: any;
15 | $Modal: any;
16 | }
17 | }
--------------------------------------------------------------------------------
/packages/app2/src/store/Actions.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description:
3 | * @Author: Gouxinyu
4 | * @Date: 2020-08-03 23:25:36
5 | */
6 | export default {
7 |
8 | }
--------------------------------------------------------------------------------
/packages/app2/src/store/Getters.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description:
3 | * @Author: Gouxinyu
4 | * @Date: 2020-08-03 23:26:11
5 | */
6 | export default {
7 | }
--------------------------------------------------------------------------------
/packages/app2/src/store/Mutations.js:
--------------------------------------------------------------------------------
1 | const mutations = {
2 | addCount(state) {
3 | state.counter += 1;
4 | }
5 | }
6 |
7 | export default mutations;
--------------------------------------------------------------------------------
/packages/app2/src/store/State.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | counter: 0
3 | }
4 |
5 | export default state;
--------------------------------------------------------------------------------
/packages/app2/src/store/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description:
3 | * @Author: Gouxinyu
4 | * @Date: 2020-08-02 23:04:30
5 | */
6 |
7 | import { createStore } from 'vuex';
8 | import state from './State';
9 | import mutations from './Mutations';
10 | import actions from './Actions';
11 | import getters from './Getters';
12 |
13 | const store = createStore({
14 | state,
15 | mutations,
16 | actions,
17 | getters
18 | })
19 |
20 | export default store;
--------------------------------------------------------------------------------
/packages/app2/webpack.dev.config.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description: webpack5配置
3 | * @Author: austin wong
4 | * @Date: 2020-11-09 00:27:35
5 | */
6 | const path = require('path');
7 | const { HotModuleReplacementPlugin, IgnorePlugin } = require('webpack');
8 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
9 | const HtmlWebpackPlugin = require('html-webpack-plugin');
10 | const { VueLoaderPlugin } = require('vue-loader');
11 | const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
12 |
13 | const config = {
14 | mode: 'development',
15 | entry: './src/main.js',
16 | output: {
17 | filename: 'index.js',
18 | path: path.resolve(__dirname, 'dist')
19 | },
20 | devServer: {
21 | contentBase: false,
22 | // publicPath: './dist',
23 | hot: true,
24 | port: 3002,
25 | open: false,
26 | // hotOnly: true,
27 | compress: true,
28 | overlay: true,
29 | disableHostCheck: true, // 新增该配置项
30 | },
31 | watchOptions: {
32 | ignored: /node_modules/
33 | },
34 | plugins: [
35 | new CleanWebpackPlugin(),
36 | new HtmlWebpackPlugin({
37 | title: 'Hot Module Replacement',
38 | template: 'index.html'
39 | }),
40 | new IgnorePlugin(/^\.\/locale$/, /moment$/),
41 | new HotModuleReplacementPlugin(),
42 | new VueLoaderPlugin(),
43 | new ModuleFederationPlugin({
44 | name: "app2",
45 | // library: { type: "var", name: "yj-nc" },
46 | filename: "remoteEntry.js",
47 | remotes: {
48 | 'main': "main@http://localhost:3000/remoteEntry.js"
49 | },
50 | exposes: {
51 | './APP': "./src/pages/App.vue"
52 | },
53 | shared: []
54 | })
55 | ],
56 | module: {
57 | rules: [
58 | // babel使用runtime,避免将不需要的代码注入
59 | {
60 | test: /\.js$/,
61 | exclude: /node_modules/,
62 | use: [{
63 | loader: 'babel-loader',
64 | options: {
65 | // cacheDirectory: true,
66 | presets: ['@babel/preset-env'],
67 | plugins: [
68 | '@babel/plugin-transform-runtime', ['import', {
69 | "libraryName": "antd",
70 | "style": true, // or 'css'
71 | }, 'antd']
72 | ]
73 | }
74 | }],
75 | },
76 | {
77 | test: /\.vue$/,
78 | loader: 'vue-loader'
79 | },
80 | {
81 | test: /\.css$/,
82 | use: ['style-loader', 'css-loader']
83 | },
84 | {
85 | test: /\.less$/,
86 | use: ['style-loader', 'css-loader',
87 | {
88 | loader: 'less-loader',
89 | options: {
90 | lessOptions: {
91 | modifyVars: {
92 | 'primary-color': '#4608e2',
93 | 'link-color': '#4608e2',
94 | 'border-radius-base': '20px',
95 | },
96 | javascriptEnabled: true,
97 | }
98 | }
99 | }
100 | ],
101 | }
102 | ]
103 | },
104 | resolve: {
105 | extensions: ['.js']
106 | },
107 | };
108 |
109 |
110 | module.exports = (env) => {
111 | console.log(`当前执行${env.mode}模式`);
112 |
113 | return config;
114 | }
--------------------------------------------------------------------------------
/packages/app2/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description: webpack5配置
3 | * @Author: austin wong
4 | * @Date: 2021-04-16 13:26:28
5 | */
6 | const path = require('path');
7 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
8 | const HtmlWebpackPlugin = require('html-webpack-plugin');
9 | const CopyWebpackPlugin = require('copy-webpack-plugin');
10 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
11 | const { VueLoaderPlugin } = require('vue-loader');
12 | const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
13 |
14 | const config = {
15 | mode: 'production',
16 | entry: './src/main.js',
17 | output: {
18 | filename: 'index.js',
19 | path: path.resolve(__dirname, 'dist')
20 | },
21 | plugins: [
22 | new CleanWebpackPlugin(),
23 | new HtmlWebpackPlugin({
24 | title: 'Hot Module Replacement',
25 | template: 'index.html'
26 | }),
27 | new CopyWebpackPlugin({
28 | patterns: [
29 | {
30 | from: 'src/assets',
31 | to: 'assets'
32 | },
33 | ]
34 | }),
35 | new MiniCssExtractPlugin({
36 | filename: './index.css'
37 | }),
38 | new VueLoaderPlugin(),
39 | new ModuleFederationPlugin({
40 | name: "app1",
41 | // library: { type: "var", name: "yj-nc" },
42 | filename: "remoteEntry.js",
43 | remotes: {
44 | 'main': "main@http://localhost:3000/remoteEntry.js"
45 | },
46 | exposes: {
47 | './Test': "./src/components/test.vue"
48 | },
49 | shared: []
50 | })
51 | ],
52 | module: {
53 | rules: [
54 | // babel使用runtime,避免将不需要的代码注入
55 | {
56 | test: /\.js$/,
57 | exclude: /node_modules/,
58 | use: [{
59 | loader: 'babel-loader',
60 | options: {
61 | cacheDirectory: true,
62 | presets: ['@babel/preset-env'],
63 | plugins: [
64 | ['import', {
65 | "libraryName": "antd",
66 | "style": true, // or 'css'
67 | }, 'antd']
68 | ]
69 | }
70 | }],
71 | },
72 | {
73 | test: /\.vue$/,
74 | use: ['vue-loader']
75 | },
76 | {
77 | test: /\.css$/,
78 | use: [MiniCssExtractPlugin.loader, 'css-loader']
79 | },
80 | {
81 | test: /\.less$/,
82 | use: [MiniCssExtractPlugin.loader, 'css-loader', {
83 | loader: 'less-loader',
84 | options: {
85 | lessOptions: {
86 | modifyVars: {
87 | 'primary-color': '#4608e2',
88 | 'link-color': '#4608e2',
89 | 'border-radius-base': '20px',
90 | },
91 | javascriptEnabled: true,
92 | }
93 | }
94 | }]
95 | }
96 | ]
97 | },
98 | resolve: {
99 | extensions: ['.js']
100 | },
101 | };
102 |
103 | module.exports = (env) => {
104 | console.log(`当前执行${env.mode}模式`);
105 | // 如果是开发模式,
106 |
107 | return config;
108 | }
--------------------------------------------------------------------------------
/packages/main/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | dist/
3 | package-lock.json
--------------------------------------------------------------------------------
/packages/main/index.html:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | webpack5
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/packages/main/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "main",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "serve": "webpack-dev-server --config webpack.dev.config.js --env.mode development --watch --profile",
9 | "build": "webpack --config webpack.prod.config.js --env.mode production"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "@babel/core": "^7.12.9",
16 | "@babel/plugin-transform-runtime": "^7.12.1",
17 | "@babel/preset-env": "^7.12.7",
18 | "@vue/compiler-sfc": "^3.0.11",
19 | "babel-loader": "^8.2.2",
20 | "babel-plugin-import": "^1.13.3",
21 | "clean-webpack-plugin": "^3.0.0",
22 | "copy-webpack-plugin": "^8.1.1",
23 | "css-loader": "^5.0.1",
24 | "file-loader": "^6.2.0",
25 | "html-webpack-plugin": "^4.5.1",
26 | "image-webpack-loader": "^7.0.1",
27 | "mini-css-extract-plugin": "^1.6.0",
28 | "sass": "^1.37.5",
29 | "sass-loader": "^11.1.1",
30 | "style-loader": "^2.0.0",
31 | "url-loader": "^4.1.1",
32 | "vue-loader": "^16.0.0-rc.1",
33 | "webpack": "^5.6.0",
34 | "webpack-cli": "^3.3.12",
35 | "webpack-dev-server": "^3.11.2",
36 | "axios": "^0.20.0"
37 | },
38 | "dependencies": {
39 | "@babel/runtime": "^7.12.5",
40 | "ant-design-vue": "^2.1.4",
41 | "cross-env": "^7.0.3",
42 | "serve": "^11.3.2",
43 | "vue": "^3.0.11",
44 | "vue-router": "^4.0.8",
45 | "vuex": "^4.0.0"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/packages/main/src/api/login.js:
--------------------------------------------------------------------------------
1 | import request from '../utils/request'
2 | const baseUrl = `http://test.yunjian613.com`
3 |
4 | // 登录
5 | export function login(data) {
6 | debugger
7 | return request({
8 | url: baseUrl + '/java-auth/oauth/token' + data.url,
9 | method: 'post',
10 | data,
11 | })
12 | }
--------------------------------------------------------------------------------
/packages/main/src/assets/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/120397474/webpack5-moduleFederation/0549420becefbb50820522e8b332e26b5966c3df/packages/main/src/assets/back.png
--------------------------------------------------------------------------------
/packages/main/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/120397474/webpack5-moduleFederation/0549420becefbb50820522e8b332e26b5966c3df/packages/main/src/assets/logo.png
--------------------------------------------------------------------------------
/packages/main/src/layout/Header.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
32 |
33 |
34 |
35 |
89 |
90 |
--------------------------------------------------------------------------------
/packages/main/src/main.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description: 开发模式,vue需要完整入口文件
3 | * @Author: austin wong
4 | * @Date: 2021-04-16 13:26:28
5 | */
6 | import { createApp, defineAsyncComponent } from "vue";
7 | import box from "./pages/App.vue";
8 | import store from './store';
9 | import router from './router'
10 | import Antd from 'ant-design-vue'
11 | import 'ant-design-vue/dist/antd.less';
12 |
13 | const Content = defineAsyncComponent(() =>
14 | import ('app1/Test'))
15 |
16 | const Content1 = defineAsyncComponent(() =>
17 | import ('app2/APP'))
18 |
19 | const app = createApp(box);
20 |
21 | app.component('ContentElement', Content)
22 | app.component('ContentElement1', Content1)
23 | app.use(store).use(Antd).use(router).mount('#app');
--------------------------------------------------------------------------------
/packages/main/src/pages/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
15 |
--------------------------------------------------------------------------------
/packages/main/src/pages/Home.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/packages/main/src/pages/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
大屏管理系统
7 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | 登 录
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
96 |
97 |
--------------------------------------------------------------------------------
/packages/main/src/router/index.js:
--------------------------------------------------------------------------------
1 | import { createRouter, createWebHistory } from "vue-router";
2 |
3 | const routes = [{
4 | path: "/Login",
5 | component: () =>
6 | import("../pages/Login.vue")
7 | },
8 | {
9 | path: "/",
10 | component: () =>
11 | import("../pages/Home.vue")
12 | }
13 | ];
14 |
15 | const router = createRouter({
16 | history: createWebHistory(),
17 | routes
18 | });
19 |
20 | export default router;
--------------------------------------------------------------------------------
/packages/main/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * @description:
3 | * @Author: austin wong
4 | * @Date: 2021-04-16 13:26:28
5 | */
6 | declare module '*.vue' {
7 | import Vue from 'vue';
8 | export default Vue;
9 | }
10 |
11 | declare module "vue/types/vue" {
12 | interface Vue {
13 | $http: any;
14 | $Message: any;
15 | $Modal: any;
16 | }
17 | }
--------------------------------------------------------------------------------
/packages/main/src/store/Actions.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description:
3 | * @Author: austin wong
4 | * @Date: 2021-04-16 13:26:28
5 | */
6 | export default {
7 |
8 | }
--------------------------------------------------------------------------------
/packages/main/src/store/Getters.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description:
3 | * @Author: austin wong
4 | * @Date: 2021-04-16 13:26:28
5 | */
6 | export default {
7 | }
--------------------------------------------------------------------------------
/packages/main/src/store/Mutations.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description:
3 | * @Author: austin wong
4 | * @Date: 2021-04-16 13:26:28
5 | */
6 | export default {
7 | }
--------------------------------------------------------------------------------
/packages/main/src/store/State.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description:
3 | * @Author: austin wong
4 | * @Date: 2021-04-16 13:26:28
5 | */
6 | export default {
7 | }
--------------------------------------------------------------------------------
/packages/main/src/store/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @description:
3 | * @Author: austin wong
4 | * @Date: 2021-04-16 13:26:28
5 | */
6 |
7 | import { createStore } from 'vuex';
8 | import state from './State';
9 | import mutations from './Mutations';
10 | import actions from './Actions';
11 | import getters from './Getters';
12 |
13 | const store = createStore({
14 | // state,
15 | // mutations,
16 | // actions,
17 | // getters
18 | })
19 |
20 | export default store;
--------------------------------------------------------------------------------
/packages/main/src/utils/index.js:
--------------------------------------------------------------------------------
1 | const timestampToTime = timestamp => {
2 | let date = new Date(timestamp); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
3 | let Y = date.getFullYear() + "-";
4 | let M =
5 | (date.getMonth() + 1 < 10
6 | ? "0" + (date.getMonth() + 1)
7 | : date.getMonth() + 1) + "-";
8 | let D = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " ";
9 | let h =
10 | (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
11 | let m =
12 | (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) +
13 | ":";
14 | let s = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
15 | return Y + M + D + h + m + s;
16 | };
17 | /**
18 | * 存储localStorage
19 | */
20 | const setStore = (name, content) => {
21 | if (!name) return;
22 | if (typeof content !== "string") {
23 | content = JSON.stringify(content);
24 | }
25 | window.localStorage.setItem(name, content);
26 | };
27 |
28 | /**
29 | * 获取localStorage
30 | */
31 | const getStore = name => {
32 | if (!name) return;
33 | return window.localStorage.getItem(name);
34 | };
35 |
36 | /**
37 | * 删除localStorage
38 | */
39 | const removeStore = name => {
40 | if (!name) return;
41 | window.localStorage.removeItem(name);
42 | };
43 | //验证码生成
44 | const createCode = name => {
45 | let code = "";
46 | let codeLength = 4; //验证码的长度
47 | let random = [
48 | 0,
49 | 1,
50 | 2,
51 | 3,
52 | 4,
53 | 5,
54 | 6,
55 | 7,
56 | 8,
57 | 9,
58 | "A",
59 | "B",
60 | "C",
61 | "D",
62 | "E",
63 | "F",
64 | "G",
65 | "H",
66 | "I",
67 | "J",
68 | "K",
69 | "L",
70 | "M",
71 | "N",
72 | "O",
73 | "P",
74 | "Q",
75 | "R",
76 | "S",
77 | "T",
78 | "U",
79 | "V",
80 | "W",
81 | "X",
82 | "Y",
83 | "Z"
84 | ]; //随机数
85 | for (let i = 0; i < codeLength; i++) {
86 | //循环操作
87 | let index = Math.floor(Math.random() * 36); //取得随机数的索引(0~35)
88 | code += random[index]; //根据索引取得随机数加到code上
89 | }
90 | return code; //把code值赋给验证码
91 | };
92 | /**
93 | * 设置cookie
94 | **/
95 | function setCookie(name, value, day) {
96 | let date = new Date();
97 | date.setDate(date.getDate() + day);
98 | document.cookie = name + "=" + value + ";expires=" + date;
99 | }
100 |
101 | /**
102 | * 获取cookie
103 | **/
104 | function getCookie(name) {
105 | let reg = RegExp(name + "=([^;]+)");
106 | let arr = document.cookie.match(reg);
107 | if (arr) {
108 | return arr[1];
109 | } else {
110 | return "";
111 | }
112 | }
113 |
114 | /**
115 | * 删除cookie
116 | **/
117 | function delCookie(name) {
118 | setCookie(name, null, -1);
119 | }
120 |
121 | /**
122 | * 导出
123 | **/
124 | export {
125 | timestampToTime,
126 | setStore,
127 | getStore,
128 | removeStore,
129 | setCookie,
130 | getCookie,
131 | delCookie,
132 | createCode
133 | };
--------------------------------------------------------------------------------
/packages/main/src/utils/request.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | // axios 配置
4 | axios.defaults.timeout = 1800000
5 | axios.defaults.baseURL = ''
6 |
7 | // http request 拦截器
8 | axios.interceptors.request.use(
9 | config => {
10 | const USER_TOKEN = sessionStorage.getItem('token')
11 |
12 | if (USER_TOKEN) {
13 | config.headers.common['Authorization'] = `${USER_TOKEN}`
14 | }
15 | return config
16 | },
17 | err => {
18 | return Promise.reject(err)
19 | }
20 | )
21 |
22 | // http response 拦截器
23 | axios.interceptors.response.use(
24 | response => {
25 | // response 里面可以判断code 如果401 就跳转登录
26 | return response
27 | },
28 | err => {
29 | return Promise.reject(err)
30 | }
31 | )
32 |
33 | export default axios
--------------------------------------------------------------------------------
/packages/main/webpack.dev.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const { HotModuleReplacementPlugin, IgnorePlugin } = require('webpack');
3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
4 | const HtmlWebpackPlugin = require('html-webpack-plugin');
5 | const { VueLoaderPlugin } = require('vue-loader');
6 | const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
7 | const MiniCssExtractPlugin = require("mini-css-extract-plugin");
8 | const config = {
9 | mode: 'development',
10 | entry: './src/main.js',
11 | output: {
12 | filename: 'index.js',
13 | path: path.resolve(__dirname, 'dist')
14 | },
15 | devServer: {
16 | contentBase: false,
17 | // publicPath: './dist',
18 | hot: true,
19 | port: 3000,
20 | open: true,
21 | // hotOnly: true,
22 | compress: true,
23 | overlay: true,
24 | disableHostCheck: true, // 新增该配置项
25 | proxy: {
26 | '/': {
27 | //代理api
28 | target: 'http://test.yunjian613.com',
29 | // changeOrigin: true, //是否跨域
30 | // ws: true, // proxy websockets
31 | pathRewrite: {
32 | '': '/java'
33 | }
34 | }
35 | }
36 | },
37 | watchOptions: {
38 | ignored: /node_modules/
39 | },
40 | plugins: [
41 | new CleanWebpackPlugin(),
42 | new HtmlWebpackPlugin({
43 | title: 'Hot Module Replacement',
44 | template: 'index.html'
45 | }),
46 | new IgnorePlugin(/^\.\/locale$/, /moment$/),
47 | new HotModuleReplacementPlugin(),
48 | new VueLoaderPlugin(),
49 | new MiniCssExtractPlugin(),
50 | new ModuleFederationPlugin({
51 | name: "main",
52 | // library: { type: "var", name: "main" },
53 | filename: "remoteEntry.js",
54 | remotes: {
55 | 'app1': "app1@http://localhost:3001/remoteEntry.js",
56 | 'app2': "app2@http://localhost:3002/remoteEntry.js"
57 | },
58 | exposes: {},
59 | shared: []
60 | })
61 | ],
62 | module: {
63 | rules: [
64 | // babel使用runtime,避免将不需要的代码注入
65 | {
66 | test: /\.js$/,
67 | exclude: /node_modules/,
68 | use: [{
69 | loader: 'babel-loader',
70 | options: {
71 | // cacheDirectory: true,
72 | presets: ['@babel/preset-env'],
73 | plugins: [
74 | '@babel/plugin-transform-runtime', ['import', {
75 | "libraryName": "antd",
76 | "style": true, // or 'css'
77 | }, 'antd']
78 | ]
79 | }
80 | }],
81 | },
82 | {
83 | test: /\.vue$/,
84 | loader: 'vue-loader'
85 | },
86 | {
87 | test: /\.css$/,
88 | use: ['style-loader', 'css-loader']
89 | },
90 | {
91 | test: /\.scss$/,
92 | use: ["style-loader", "css-loader", "sass-loader"]
93 | },
94 | {
95 | test: /\.less$/,
96 | use: [MiniCssExtractPlugin.loader, 'css-loader', {
97 | loader: 'less-loader',
98 | options: {
99 | lessOptions: {
100 | modifyVars: {
101 | 'primary-color': '#4608e2',
102 | 'link-color': '#4608e2',
103 | 'border-radius-base': '20px',
104 | },
105 | javascriptEnabled: true,
106 | }
107 | }
108 | }]
109 | },
110 | // file-laoder加载图片
111 | {
112 | test: /\.(jpg|png|jpeg|gif|svg)$/,
113 | use: ['file-loader']
114 | }
115 | ]
116 | },
117 | resolve: {
118 | extensions: ['.js']
119 | },
120 | };
121 |
122 |
123 | module.exports = (env) => {
124 | console.log(`当前执行${env.mode}模式`);
125 |
126 | return config;
127 | }
--------------------------------------------------------------------------------
/packages/main/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const { HotModuleReplacementPlugin, IgnorePlugin } = require('webpack');
3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
4 | const HtmlWebpackPlugin = require('html-webpack-plugin');
5 | const { VueLoaderPlugin } = require('vue-loader');
6 | const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
7 | const MiniCssExtractPlugin = require("mini-css-extract-plugin");
8 | const config = {
9 | mode: 'development',
10 | entry: './src/main.js',
11 | output: {
12 | filename: 'index.js',
13 | path: path.resolve(__dirname, 'dist')
14 | },
15 | devServer: {
16 | contentBase: false,
17 | // publicPath: './dist',
18 | hot: true,
19 | port: 3000,
20 | open: true,
21 | // hotOnly: true,
22 | compress: true,
23 | overlay: true,
24 | disableHostCheck: true, // 新增该配置项
25 | },
26 | watchOptions: {
27 | ignored: /node_modules/
28 | },
29 | plugins: [
30 | new CleanWebpackPlugin(),
31 | new HtmlWebpackPlugin({
32 | title: 'Hot Module Replacement',
33 | template: 'index.html'
34 | }),
35 | new IgnorePlugin(/^\.\/locale$/, /moment$/),
36 | new HotModuleReplacementPlugin(),
37 | new VueLoaderPlugin(),
38 | new MiniCssExtractPlugin(),
39 | new ModuleFederationPlugin({
40 | name: "main",
41 | // library: { type: "var", name: "main" },
42 | filename: "remoteEntry.js",
43 | remotes: {
44 | 'app1': "app1@http://localhost:3001/remoteEntry.js",
45 | 'app2': "app2@http://localhost:3002/remoteEntry.js"
46 | },
47 | exposes: {},
48 | shared: []
49 | })
50 | ],
51 | module: {
52 | rules: [
53 | // babel使用runtime,避免将不需要的代码注入
54 | {
55 | test: /\.js$/,
56 | exclude: /node_modules/,
57 | use: [{
58 | loader: 'babel-loader',
59 | options: {
60 | // cacheDirectory: true,
61 | presets: ['@babel/preset-env'],
62 | plugins: [
63 | '@babel/plugin-transform-runtime', ['import', {
64 | "libraryName": "antd",
65 | "style": true, // or 'css'
66 | }, 'antd']
67 | ]
68 | }
69 | }],
70 | },
71 | {
72 | test: /\.vue$/,
73 | loader: 'vue-loader'
74 | },
75 | {
76 | test: /\.css$/,
77 | use: ['style-loader', 'css-loader']
78 | },
79 | {
80 | test: /\.scss$/,
81 | use: ["style-loader", "css-loader", "sass-loader"]
82 | },
83 | {
84 | test: /\.less$/,
85 | use: [MiniCssExtractPlugin.loader, 'css-loader', {
86 | loader: 'less-loader',
87 | options: {
88 | lessOptions: {
89 | modifyVars: {
90 | 'primary-color': '#4608e2',
91 | 'link-color': '#4608e2',
92 | 'border-radius-base': '20px',
93 | },
94 | javascriptEnabled: true,
95 | }
96 | }
97 | }]
98 | },
99 | // file-laoder加载图片
100 | {
101 | test: /\.(jpg|png|jpeg|gif|svg)$/,
102 | use: ['file-loader']
103 | }
104 | ]
105 | },
106 | resolve: {
107 | extensions: ['.js']
108 | },
109 | };
110 |
111 |
112 | module.exports = (env) => {
113 | console.log(`当前执行${env.mode}模式`);
114 |
115 | return config;
116 | }
--------------------------------------------------------------------------------