9 changed files with 576 additions and 0 deletions
			
			
		| 
		 After Width: | Height: | Size: 7.9 KiB  | 
@ -0,0 +1,32 @@ | 
				
			|||||
 | 
					/** | 
				
			||||
 | 
					 * 用于自动生成前端组件 | 
				
			||||
 | 
					 * 通过 src/routes/routes.json 文件构建 src/components/index.ts 文件 | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					const fs = require('fs'); | 
				
			||||
 | 
					const Json5 =require('json5'); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// 解析前端路由配置文件 | 
				
			||||
 | 
					const routesJson = Json5.parse(fs.readFileSync('./src/routes/routes.json', 'utf8')); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					let content =''; | 
				
			||||
 | 
					content +='/**\n'; | 
				
			||||
 | 
					content +=' * 此文件为自动生成文件,请勿修改\n'; | 
				
			||||
 | 
					content +=' */\n\n'; | 
				
			||||
 | 
					for(const route of routesJson){ | 
				
			||||
 | 
					  const componentName =route.component.substring(route.component.lastIndexOf('.')+1); | 
				
			||||
 | 
					  const componentPath =route.componentPath; | 
				
			||||
 | 
					  content +=`import ${componentName} from '${componentPath}';\n`; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					content +='\n'; | 
				
			||||
 | 
					content +='const localComponents = { \n'; | 
				
			||||
 | 
					for(const route of routesJson){ | 
				
			||||
 | 
					  const componentName =route.component.substring(route.component.lastIndexOf('.')+1); | 
				
			||||
 | 
					  content +=`'${route.component}': ${componentName},\n`; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					content +='}\n\n'; | 
				
			||||
 | 
					content +='export default localComponents;\n'; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					fs.writeFileSync('./src/components/index.ts', content); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					console.info('components generated!'); | 
				
			||||
@ -0,0 +1,173 @@ | 
				
			|||||
 | 
					/** | 
				
			||||
 | 
					 * 用于将前端模块注册到后端服务器 | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					const packageJson = require('./package.json'); | 
				
			||||
 | 
					const { ModuleFederationPlugin } = require('webpack').container; | 
				
			||||
 | 
					const Server = require('webpack-dev-server'); | 
				
			||||
 | 
					const mf = require('./webpack.config.mf.cjs'); | 
				
			||||
 | 
					const fs = require('fs'); | 
				
			||||
 | 
					const http = require('http'); | 
				
			||||
 | 
					const https = require('https'); | 
				
			||||
 | 
					const Json5 =require('json5'); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// 解析前端注册器配置文件 | 
				
			||||
 | 
					const frontendRegisterConfigure = Json5.parse(fs.readFileSync('./frontend-register.json', 'utf8')); | 
				
			||||
 | 
					// 解析前端路由配置文件 | 
				
			||||
 | 
					const frontendRoutes =Json5.parse(fs.readFileSync('./src/routes/routes.json', 'utf8')); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/** | 
				
			||||
 | 
					 * 远程组件注册器类 | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					class RemoteFrontEndModuleRegister { | 
				
			||||
 | 
					  /** | 
				
			||||
 | 
					   * 构造函数,传入配置信息, 包括远程和本地服务器配置信息 | 
				
			||||
 | 
					   * 配置信息定义格式如下: | 
				
			||||
 | 
					   *     // 远程服务器配置信息 | 
				
			||||
 | 
					   *     remoteServerConfig: { | 
				
			||||
 | 
					   *       protocol: 'http', | 
				
			||||
 | 
					   *       host: 'localhost', | 
				
			||||
 | 
					   *       port: 8080, | 
				
			||||
 | 
					   *       path: '/api/system/frontend/regist', | 
				
			||||
 | 
					   *     }, | 
				
			||||
 | 
					   *     // 本地服务器配置信息 | 
				
			||||
 | 
					   *     localServerConfig: { | 
				
			||||
 | 
					   *       protocol: devServer.options.server.type, | 
				
			||||
 | 
					   *       host: Server.internalIPSync("v4"), | 
				
			||||
 | 
					   *       port: devServer.options.port, | 
				
			||||
 | 
					   *       path: '/', | 
				
			||||
 | 
					   *     } | 
				
			||||
 | 
					   * @param devServer webpack dev server 对象 | 
				
			||||
 | 
					   */ | 
				
			||||
 | 
					  constructor(devServer) { | 
				
			||||
 | 
					    if (!devServer) { | 
				
			||||
 | 
					      throw new Error('webpack-dev-server is not defined'); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    this.devServer = devServer; | 
				
			||||
 | 
					    this.registSuccess = null; | 
				
			||||
 | 
					    this.remoteServerConfig = { | 
				
			||||
 | 
					      protocol: frontendRegisterConfigure.protocol, | 
				
			||||
 | 
					      host: frontendRegisterConfigure.host, | 
				
			||||
 | 
					      port: frontendRegisterConfigure.port, | 
				
			||||
 | 
					      path: frontendRegisterConfigure.path, | 
				
			||||
 | 
					    }; | 
				
			||||
 | 
					    this.localServerConfig = { | 
				
			||||
 | 
					      protocol: devServer.options.server.type, | 
				
			||||
 | 
					      host: Server.internalIPSync("v4"), | 
				
			||||
 | 
					      port: devServer.options.port, | 
				
			||||
 | 
					      path: '/', | 
				
			||||
 | 
					    }; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  /** | 
				
			||||
 | 
					   * 周期性向服务器注册前端模块 | 
				
			||||
 | 
					   * @param delay 延迟执行(单位:毫秒) | 
				
			||||
 | 
					   * @param interval 固定频率执行(单位:毫秒) | 
				
			||||
 | 
					   */ | 
				
			||||
 | 
					  regist(delay,interval) { | 
				
			||||
 | 
					    if(frontendRegisterConfigure.enable){ | 
				
			||||
 | 
					      setTimeout(() => { | 
				
			||||
 | 
					        let remoteServerUrl = this.remoteServerConfig.protocol + '//' + this.remoteServerConfig.host + ':' + this.remoteServerConfig.port + this.remoteServerConfig.path; | 
				
			||||
 | 
					        console.info('regist frontend module to server --> ' + remoteServerUrl); | 
				
			||||
 | 
					        setInterval(this.doRegist.bind(this), delay); | 
				
			||||
 | 
					      }, delay); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  /** | 
				
			||||
 | 
					   * 向服务器注册前端模块 | 
				
			||||
 | 
					   */ | 
				
			||||
 | 
					  doRegist() { | 
				
			||||
 | 
					    const data = JSON.stringify(this.getRegistJson()); | 
				
			||||
 | 
					    if (data) { | 
				
			||||
 | 
					      let request = this.getRequest(this.remoteServerConfig.protocol); | 
				
			||||
 | 
					      let This = this; | 
				
			||||
 | 
					      request.on('error', error => { | 
				
			||||
 | 
					        if (This.registSuccess == null || This.registSuccess) { | 
				
			||||
 | 
					          This.registSuccess = false; | 
				
			||||
 | 
					          console.error('regist frontend module to server, Failed!', error); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					      }); | 
				
			||||
 | 
					      request.write(data); | 
				
			||||
 | 
					      request.end(); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  /** | 
				
			||||
 | 
					   * 获取前端模块的注册信息 | 
				
			||||
 | 
					   * @returns 前端模块的注册信息 | 
				
			||||
 | 
					   */ | 
				
			||||
 | 
					  getRegistJson() { | 
				
			||||
 | 
					    return { | 
				
			||||
 | 
					      protocol: this.localServerConfig.protocol, | 
				
			||||
 | 
					      host: this.localServerConfig.host, | 
				
			||||
 | 
					      port: this.localServerConfig.port, | 
				
			||||
 | 
					      contextPath: this.localServerConfig.contextPath, | 
				
			||||
 | 
					      name: packageJson.name, | 
				
			||||
 | 
					      components: this.getComponents(), | 
				
			||||
 | 
					      routes: frontendRoutes, | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  /** | 
				
			||||
 | 
					   * 获取前端模块的注册信息(组件集合) | 
				
			||||
 | 
					   * @returns 前端模块的注册信息(组件集合) | 
				
			||||
 | 
					   */ | 
				
			||||
 | 
					  getComponents() { | 
				
			||||
 | 
					    const plugins = mf.plugins; | 
				
			||||
 | 
					    for (let i = 0; i < plugins.length; i++) { | 
				
			||||
 | 
					      const plugin = plugins[i]; | 
				
			||||
 | 
					      if (plugin instanceof ModuleFederationPlugin) { | 
				
			||||
 | 
					        const exposes = plugin._options.exposes; | 
				
			||||
 | 
					        if (exposes) { | 
				
			||||
 | 
					          const components = []; | 
				
			||||
 | 
					          let keyIndex = 0; | 
				
			||||
 | 
					          for (let key in exposes) { | 
				
			||||
 | 
					            components[keyIndex] = key; | 
				
			||||
 | 
					            keyIndex++; | 
				
			||||
 | 
					          } | 
				
			||||
 | 
					          return components; | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					      } | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    return null; | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  /** | 
				
			||||
 | 
					   * 获取 http/https 请求 | 
				
			||||
 | 
					   * @param {*} protocol 请求协议 | 
				
			||||
 | 
					   */ | 
				
			||||
 | 
					  getRequest(protocol) { | 
				
			||||
 | 
					    let request = http; | 
				
			||||
 | 
					    if (protocol == 'https:') { | 
				
			||||
 | 
					      request = https; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    let This = this; | 
				
			||||
 | 
					    return request.request({ | 
				
			||||
 | 
					      protocol: this.remoteServerConfig.protocol + ":", | 
				
			||||
 | 
					      host: this.remoteServerConfig.host, | 
				
			||||
 | 
					      port: this.remoteServerConfig.port, | 
				
			||||
 | 
					      path: this.remoteServerConfig.path, | 
				
			||||
 | 
					      method: 'POST', | 
				
			||||
 | 
					      headers: { | 
				
			||||
 | 
					        'Content-Type': 'application/json' | 
				
			||||
 | 
					      } | 
				
			||||
 | 
					    }, request => { | 
				
			||||
 | 
					      request.setEncoding('utf-8'); | 
				
			||||
 | 
					      request.on('data', d => { | 
				
			||||
 | 
					        const data = JSON.parse(d); | 
				
			||||
 | 
					        if (data.code === 200) { | 
				
			||||
 | 
					          if (This.registSuccess == null || !This.registSuccess) { | 
				
			||||
 | 
					            This.registSuccess = true; | 
				
			||||
 | 
					            console.info('regist frontend module to server, Success!'); | 
				
			||||
 | 
					          } | 
				
			||||
 | 
					        } else { | 
				
			||||
 | 
					          console.error('regist frontend module to server, Failed!', d); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					      }) | 
				
			||||
 | 
					    }); | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					module.exports = { | 
				
			||||
 | 
					  RemoteFrontEndModuleRegister | 
				
			||||
 | 
					} | 
				
			||||
@ -0,0 +1,159 @@ | 
				
			|||||
 | 
					/** | 
				
			||||
 | 
					 * webpack 通用配置 | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					const path = require('path');                                     // path | 
				
			||||
 | 
					const webpack = require('webpack');                               // webpack | 
				
			||||
 | 
					const json5 = require('json5');                                   // json5 | 
				
			||||
 | 
					const HtmlWebpackPlugin = require('html-webpack-plugin');         // webpack html 生成插件 | 
				
			||||
 | 
					const CopyWebpackPlugin = require('copy-webpack-plugin');         // webpack copy 插件 | 
				
			||||
 | 
					const MiniCssExtractPlugin = require('mini-css-extract-plugin');  // 抽取 css 插件 | 
				
			||||
 | 
					const { VueLoaderPlugin } = require('vue-loader');                // vue loader 插件 | 
				
			||||
 | 
					const ESLintPlugin = require('eslint-webpack-plugin');            // eslint 插件 | 
				
			||||
 | 
					const packageJson = require('./package.json');                    // package.json | 
				
			||||
 | 
					const projectName =packageJson.name;                              // 项目名称 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					module.exports = { | 
				
			||||
 | 
					  // 入口文件 | 
				
			||||
 | 
					  entry: './src/main', | 
				
			||||
 | 
					  // 输出 | 
				
			||||
 | 
					  output: { | 
				
			||||
 | 
					    // 输出路径(为兼容后端和多个前端项目) | 
				
			||||
 | 
					    // 1. 兼容后端: 将 dist 目录作为资源目录, 其中 public 种的静态资源可以直接访问 | 
				
			||||
 | 
					    // 2. 兼容多个前端项目: 每个项目发布到 public 目录下的唯一项目名称目录 | 
				
			||||
 | 
					    path: path.resolve(__dirname, `dist/public/${projectName}`), | 
				
			||||
 | 
					    // 输出文件名 | 
				
			||||
 | 
					    filename: `javascript/[name].[contenthash:5].js`, | 
				
			||||
 | 
					    // 指定发布路径,使用 auto 可具有更多灵活性 | 
				
			||||
 | 
					    publicPath: 'auto', | 
				
			||||
 | 
					    // 每次构建时,首先删除 output.path 目录所有内容,保证每次得到最新的构建结果 | 
				
			||||
 | 
					    clean: true, | 
				
			||||
 | 
					  }, | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  module: { | 
				
			||||
 | 
					    rules: [ | 
				
			||||
 | 
					      // babel(包含处理: typescript) | 
				
			||||
 | 
					      { | 
				
			||||
 | 
					        test: /\.(t|j)s$/, | 
				
			||||
 | 
					        exclude: /node_modules/, | 
				
			||||
 | 
					        use: [ | 
				
			||||
 | 
					          { | 
				
			||||
 | 
					            loader: "babel-loader", | 
				
			||||
 | 
					            options: { | 
				
			||||
 | 
					              cacheDirectory: true, | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					          } | 
				
			||||
 | 
					        ] | 
				
			||||
 | 
					      }, | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					      // css | 
				
			||||
 | 
					      { | 
				
			||||
 | 
					        test: /\.(sa|sc|c)ss$/, | 
				
			||||
 | 
					        use: [{ | 
				
			||||
 | 
					          loader: MiniCssExtractPlugin.loader, | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					          loader: 'css-loader', | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					          loader: 'postcss-loader', | 
				
			||||
 | 
					        }] | 
				
			||||
 | 
					      }, | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					      // 字体文件 | 
				
			||||
 | 
					      { | 
				
			||||
 | 
					        test: /\.(woff|woff2|eot|ttf|otf)(\?.*)?$/, | 
				
			||||
 | 
					        type: 'asset/resource', | 
				
			||||
 | 
					        generator: { | 
				
			||||
 | 
					          filename: `fonts/[name].[contenthash:5].[ext]`, | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					      }, | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					      // json5 | 
				
			||||
 | 
					      { | 
				
			||||
 | 
					        test: /\.json$/, | 
				
			||||
 | 
					        type: 'json', | 
				
			||||
 | 
					        parser: { | 
				
			||||
 | 
					          parse: json5.parse, | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					      }, | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					      // vue loader | 
				
			||||
 | 
					      { | 
				
			||||
 | 
					        test: /\.vue$/, | 
				
			||||
 | 
					        exclude: /node_modules/, | 
				
			||||
 | 
					        use: [ | 
				
			||||
 | 
					          { | 
				
			||||
 | 
					            loader: 'vue-loader', | 
				
			||||
 | 
					          } | 
				
			||||
 | 
					        ] | 
				
			||||
 | 
					      }, | 
				
			||||
 | 
					    ], | 
				
			||||
 | 
					  }, | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  // 插件 | 
				
			||||
 | 
					  plugins: [ | 
				
			||||
 | 
					    new webpack.DefinePlugin({ | 
				
			||||
 | 
					      __VUE_OPTIONS_API__: JSON.stringify(true), | 
				
			||||
 | 
					      __VUE_PROD_DEVTOOLS__: JSON.stringify(false) | 
				
			||||
 | 
					    }), | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // 进度显示插件 | 
				
			||||
 | 
					    new webpack.ProgressPlugin(), | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // css 抽取插件 | 
				
			||||
 | 
					    new MiniCssExtractPlugin({ | 
				
			||||
 | 
					      filename: `css/[name].[contenthash:5].css`, | 
				
			||||
 | 
					      chunkFilename: `css/[name].[contenthash:5].css` | 
				
			||||
 | 
					    }), | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // 自动生成静态 index.html 文件 | 
				
			||||
 | 
					    new HtmlWebpackPlugin({ | 
				
			||||
 | 
					      template: 'public/index.html', | 
				
			||||
 | 
					      filename: `index.html`, | 
				
			||||
 | 
					      minify: false, | 
				
			||||
 | 
					      inject: 'body', | 
				
			||||
 | 
					      timestamp: new Date().getTime(), | 
				
			||||
 | 
					    }), | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // 拷贝静态资源到 output.path 指定的目录 | 
				
			||||
 | 
					    new CopyWebpackPlugin({ | 
				
			||||
 | 
					      patterns: [ | 
				
			||||
 | 
					        { | 
				
			||||
 | 
					          from: 'public', | 
				
			||||
 | 
					          toType: 'dir', | 
				
			||||
 | 
					          filter: async (resourcePath) => { | 
				
			||||
 | 
					            // 不复制 index.html 因为 index.html 已经由 HtmlWebpackPlugin 插件生成了 | 
				
			||||
 | 
					            if (resourcePath.endsWith('index.html') || resourcePath.endsWith('.DS_Store')) { | 
				
			||||
 | 
					              return false; | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            return true; | 
				
			||||
 | 
					          }, | 
				
			||||
 | 
					          info: { minimized: true }, | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					      ] | 
				
			||||
 | 
					    }), | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // vue loader 插件 | 
				
			||||
 | 
					    new VueLoaderPlugin(), | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    // eslint 插件 | 
				
			||||
 | 
					    new ESLintPlugin({ | 
				
			||||
 | 
					      fix: true, | 
				
			||||
 | 
					      formatter: 'stylish', | 
				
			||||
 | 
					      extensions: ['js', 'ts', 'vue', 'cjs'], | 
				
			||||
 | 
					      exclude: [ | 
				
			||||
 | 
					        'node_modules', | 
				
			||||
 | 
					      ], | 
				
			||||
 | 
					    }), | 
				
			||||
 | 
					  ], | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  // 配置模块如何被解析, | 
				
			||||
 | 
					  resolve: { | 
				
			||||
 | 
					    // 设置模块别名,方便引用 | 
				
			||||
 | 
					    alias: { | 
				
			||||
 | 
					      '@': path.resolve(__dirname, 'src'), | 
				
			||||
 | 
					    }, | 
				
			||||
 | 
					    // 设置支持的模块扩展名,即这些扩展名的文件可以作为模块被使用 | 
				
			||||
 | 
					    extensions: ['.ts', '.js', '.cjs', '.vue'] | 
				
			||||
 | 
					  }, | 
				
			||||
 | 
					}; | 
				
			||||
@ -0,0 +1,66 @@ | 
				
			|||||
 | 
					/** | 
				
			||||
 | 
					 * webpack module federation 配置 | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					const fs = require('fs');                                         // 文件读取 | 
				
			||||
 | 
					const Json5 =require('json5');                                    // json5  | 
				
			||||
 | 
					const { ModuleFederationPlugin } = require('webpack').container;  // webpack 模块联邦插件 | 
				
			||||
 | 
					const packageJson = require('./package.json');                    // package.json | 
				
			||||
 | 
					const projectName =packageJson.name;                              // 项目名称 | 
				
			||||
 | 
					const deps = packageJson.dependencies;                            // 项目依赖 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// 读取本地路由配置, 通过其中 component 和 componentPath 两个属性构建 webpack 模块联邦的 exposes 属性值 | 
				
			||||
 | 
					const data = fs.readFileSync('./src/routes/routes.json', 'utf8'); | 
				
			||||
 | 
					const routes =Json5.parse(data); | 
				
			||||
 | 
					const mfExposes ={}; | 
				
			||||
 | 
					for(const route of routes){ | 
				
			||||
 | 
					  mfExposes[route.component]= route.componentPath; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// 导出 webapck 配置的模块联邦部分 | 
				
			||||
 | 
					module.exports = { | 
				
			||||
 | 
					  plugins: [ | 
				
			||||
 | 
					    new ModuleFederationPlugin({ | 
				
			||||
 | 
					      // 模块联邦的模块名称 | 
				
			||||
 | 
					      name: `${projectName}`, | 
				
			||||
 | 
					      // 模块联邦的远程入口文件 | 
				
			||||
 | 
					      filename: `javascript/remoteEntry.js`, | 
				
			||||
 | 
					      // 通过浏览器 window 对象保存模块联邦对象 | 
				
			||||
 | 
					      library: { type: 'window', name: `${projectName}` }, | 
				
			||||
 | 
					      remoteType: 'window', | 
				
			||||
 | 
					      // 模块联邦的导出组件 | 
				
			||||
 | 
					      exposes: mfExposes, | 
				
			||||
 | 
					      // 模块联邦共享库 | 
				
			||||
 | 
					      shared: { | 
				
			||||
 | 
					        '@codemirror/autocomplete': { requiredVersion: deps['@codemirror/autocomplete'], singleton: true }, | 
				
			||||
 | 
					        '@codemirror/commands': { requiredVersion: deps['@codemirror/commands'], singleton: true }, | 
				
			||||
 | 
					        '@codemirror/lang-html': { requiredVersion: deps['@codemirror/lang-html'], singleton: true }, | 
				
			||||
 | 
					        '@codemirror/lang-java': { requiredVersion: deps['@codemirror/lang-java'], singleton: true }, | 
				
			||||
 | 
					        '@codemirror/lang-javascript': { requiredVersion: deps['@codemirror/lang-javascript'], singleton: true }, | 
				
			||||
 | 
					        '@codemirror/lang-json': { requiredVersion: deps['@codemirror/lang-json'], singleton: true }, | 
				
			||||
 | 
					        '@codemirror/lang-sql': { requiredVersion: deps['@codemirror/lang-sql'], singleton: true }, | 
				
			||||
 | 
					        '@codemirror/lang-xml': { requiredVersion: deps['@codemirror/lang-xml'], singleton: true }, | 
				
			||||
 | 
					        '@codemirror/language': { requiredVersion: deps['@codemirror/language'], singleton: true }, | 
				
			||||
 | 
					        '@codemirror/search': { requiredVersion: deps['@codemirror/search'], singleton: true }, | 
				
			||||
 | 
					        '@codemirror/state': { requiredVersion: deps['@codemirror/state'], singleton: true }, | 
				
			||||
 | 
					        '@codemirror/view': { requiredVersion: deps['@codemirror/view'], singleton: true }, | 
				
			||||
 | 
					        '@vueuse/core': { requiredVersion: deps['@vueuse/core'], singleton: true }, | 
				
			||||
 | 
					        'axios': { requiredVersion: deps['axios'], singleton: true }, | 
				
			||||
 | 
					        'codemirror': { requiredVersion: deps['codemirror'], singleton: true }, | 
				
			||||
 | 
					        'dayjs': { requiredVersion: deps['dayjs'], singleton: true }, | 
				
			||||
 | 
					        'echarts':{ requiredVersion: deps['echarts'], singleton: true }, | 
				
			||||
 | 
					        'exceljs':{ requiredVersion: deps['exceljs'], singleton: true }, | 
				
			||||
 | 
					        'file-saver':{ requiredVersion: deps['file-saver'], singleton: true }, | 
				
			||||
 | 
					        'luckyexcel':{ requiredVersion: deps['luckyexcel'], singleton: true }, | 
				
			||||
 | 
					        "mockjs": { requiredVersion: deps['mockjs'], singleton: true }, | 
				
			||||
 | 
					        'pinia': { requiredVersion: deps['pinia'], singleton: true }, | 
				
			||||
 | 
					        'platform-core': { requiredVersion: deps['platform-core'], singleton: true }, | 
				
			||||
 | 
					        'quasar': { requiredVersion: deps['quasar'], singleton: true }, | 
				
			||||
 | 
					        'vue': { requiredVersion: deps['vue'], singleton: true }, | 
				
			||||
 | 
					        'vue-codemirror6': { requiredVersion: deps['vue-codemirror6'], singleton: true }, | 
				
			||||
 | 
					        'vue-dompurify-html':{ requiredVersion: deps['vue-dompurify-html'], singleton: true }, | 
				
			||||
 | 
					        'vue-i18n': { requiredVersion: deps['vue-i18n'], singleton: true }, | 
				
			||||
 | 
					        'vue-router': { requiredVersion: deps['vue-router'], singleton: true }, | 
				
			||||
 | 
					      } | 
				
			||||
 | 
					    }), | 
				
			||||
 | 
					  ] | 
				
			||||
 | 
					}; | 
				
			||||
@ -0,0 +1,76 @@ | 
				
			|||||
 | 
					/** | 
				
			||||
 | 
					 * 开发环境构建 | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					const { merge } = require('webpack-merge');                       // webpack 配置合并函数 | 
				
			||||
 | 
					const common = require('./webpack.config.common.cjs');            // webpack 通用配置 | 
				
			||||
 | 
					const mf = require('./webpack.config.mf.cjs');                    // webpack 模块联邦配置 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					module.exports = merge(common, mf, { | 
				
			||||
 | 
					  mode: 'development', | 
				
			||||
 | 
					  // ------------------------------------------------------------------------------------------------------------------------------- | 
				
			||||
 | 
					  // devtool        | performance                      | comment | 
				
			||||
 | 
					  // (none)         | build:fastest, rebuild:fastest   | Recommended choice for production builds with maximum performance. | 
				
			||||
 | 
					  // eval           | build:fast,    rebuild:fastest   | Recommended choice for development builds with maximum performance. | 
				
			||||
 | 
					  // eval-source-map| build:slowest, rebuild:ok        | Recommended choice for development builds with high quality SourceMaps. | 
				
			||||
 | 
					  // source-map     | build:slowest, rebuild:slowest   | Recommended choice for production builds with high quality SourceMaps. | 
				
			||||
 | 
					  // ------------------------------------------------------------------------------------------------------------------------------- | 
				
			||||
 | 
					  devtool: 'eval-source-map', | 
				
			||||
 | 
					  optimization: { | 
				
			||||
 | 
					    minimize: false, | 
				
			||||
 | 
					    moduleIds: 'named', | 
				
			||||
 | 
					    chunkIds: 'named', | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    splitChunks: { | 
				
			||||
 | 
					      cacheGroups: { | 
				
			||||
 | 
					        'vue': { | 
				
			||||
 | 
					          name: 'vue', | 
				
			||||
 | 
					          test: /[\\/]node_modules[\\/](vue|vue-dompurify-html|vue-i18n|vue-router)[\\/]/, | 
				
			||||
 | 
					          priority: 20, | 
				
			||||
 | 
					          chunks: 'all', | 
				
			||||
 | 
					          enforce: true | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        'dnd':{ | 
				
			||||
 | 
					          name: 'dnd', | 
				
			||||
 | 
					          test: /[\\/]node_modules[\\/](vue3-dnd|react-dnd-html5-backend|@vueuse[\\/]core)[\\/]/, | 
				
			||||
 | 
					          priority: 20, | 
				
			||||
 | 
					          chunks: 'all', | 
				
			||||
 | 
					          enforce: true | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        'quasar': { | 
				
			||||
 | 
					          name: 'quasar', | 
				
			||||
 | 
					          test: /[\\/]node_modules[\\/](quasar)[\\/]/, | 
				
			||||
 | 
					          priority: 20, | 
				
			||||
 | 
					          chunks: 'all', | 
				
			||||
 | 
					          enforce: true | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        'excel': { | 
				
			||||
 | 
					          name: 'excel', | 
				
			||||
 | 
					          test: /[\\/]node_modules[\\/](exceljs|luckyexcel|)[\\/]/, | 
				
			||||
 | 
					          priority: 20, | 
				
			||||
 | 
					          chunks: 'all', | 
				
			||||
 | 
					          enforce: true | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        'platform-core': { | 
				
			||||
 | 
					          name: 'platform-core', | 
				
			||||
 | 
					          test: /[\\/]node_modules[\\/]platform-core[\\/]/, | 
				
			||||
 | 
					          priority: 20, | 
				
			||||
 | 
					          chunks: 'all', | 
				
			||||
 | 
					          enforce: true | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        'view': { | 
				
			||||
 | 
					          name: 'view', | 
				
			||||
 | 
					          test: /[\\/]view[\\/]/, | 
				
			||||
 | 
					          priority: 20, | 
				
			||||
 | 
					          chunks: 'all', | 
				
			||||
 | 
					          enforce: true | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					        'vendors': { | 
				
			||||
 | 
					          name: 'vendors', | 
				
			||||
 | 
					          test: /[\\/]node_modules[\\/]/, | 
				
			||||
 | 
					          chunks: 'all', | 
				
			||||
 | 
					          enforce: true | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					      } | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					  }, | 
				
			||||
 | 
					}); | 
				
			||||
@ -0,0 +1,35 @@ | 
				
			|||||
 | 
					/** | 
				
			||||
 | 
					 * 生产环境构建 | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); // css 压缩插件 | 
				
			||||
 | 
					const TerserPlugin = require("terser-webpack-plugin");              // js 压缩插件 | 
				
			||||
 | 
					const { merge } = require('webpack-merge');                         // webpack 配置合并函数 | 
				
			||||
 | 
					const build = require('./webpack.env.build.cjs');                   // 开发环境构建配置 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					module.exports = merge(build, { | 
				
			||||
 | 
					  mode: 'production', | 
				
			||||
 | 
					  // ------------------------------------------------------------------------------------------------------------------------------- | 
				
			||||
 | 
					  // devtool        | performance                      | comment | 
				
			||||
 | 
					  // (none)         | build:fastest, rebuild:fastest   | Recommended choice for production builds with maximum performance. | 
				
			||||
 | 
					  // eval           | build:fast,    rebuild:fastest   | Recommended choice for development builds with maximum performance. | 
				
			||||
 | 
					  // eval-source-map| build:slowest, rebuild:ok        | Recommended choice for development builds with high quality SourceMaps. | 
				
			||||
 | 
					  // source-map     | build:slowest, rebuild:slowest   | Recommended choice for production builds with high quality SourceMaps. | 
				
			||||
 | 
					  // ------------------------------------------------------------------------------------------------------------------------------- | 
				
			||||
 | 
					  devtool: 'source-map', | 
				
			||||
 | 
					  optimization: { | 
				
			||||
 | 
					    minimize: true, | 
				
			||||
 | 
					    minimizer: [ | 
				
			||||
 | 
					      new CssMinimizerPlugin(),   // css 压缩插件 | 
				
			||||
 | 
					      new TerserPlugin({          // js 压缩插件 | 
				
			||||
 | 
					        extractComments: false, | 
				
			||||
 | 
					        terserOptions: { | 
				
			||||
 | 
					          format: { | 
				
			||||
 | 
					            comments: false, | 
				
			||||
 | 
					          }, | 
				
			||||
 | 
					        }, | 
				
			||||
 | 
					      }), | 
				
			||||
 | 
					    ], | 
				
			||||
 | 
					    moduleIds: 'named', | 
				
			||||
 | 
					    chunkIds: 'named', | 
				
			||||
 | 
					  }, | 
				
			||||
 | 
					}); | 
				
			||||
@ -0,0 +1,35 @@ | 
				
			|||||
 | 
					/** | 
				
			||||
 | 
					 * 开发环境下启动 webpack dev server | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					const path = require('path');                                                     // path | 
				
			||||
 | 
					const { merge } = require('webpack-merge');                                       // webpack 配置合并函数 | 
				
			||||
 | 
					const common = require('./webpack.config.common.cjs');                            // webpack 通用配置 | 
				
			||||
 | 
					const mf = require('./webpack.config.mf.cjs');                                    // webpack 模块联邦配置 | 
				
			||||
 | 
					const { RemoteFrontEndModuleRegister } = require('./util-frontend-register.cjs'); // 远程模块注册器 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					module.exports = (env)=> merge(common, mf,{ | 
				
			||||
 | 
					  mode: 'development', | 
				
			||||
 | 
					  devtool: 'eval', | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  devServer: { | 
				
			||||
 | 
					    client: { | 
				
			||||
 | 
					      overlay: false, | 
				
			||||
 | 
					    }, | 
				
			||||
 | 
					    static: { | 
				
			||||
 | 
					      directory: path.join(__dirname, 'public'), | 
				
			||||
 | 
					    }, | 
				
			||||
 | 
					    compress: false, | 
				
			||||
 | 
					    port: 3000, | 
				
			||||
 | 
					    hot: true, | 
				
			||||
 | 
					    // 保证在出现 404 错误时,能够导航到 index.html | 
				
			||||
 | 
					    historyApiFallback: true, | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    setupMiddlewares: (middlewares, devServer) => { | 
				
			||||
 | 
					      // 注册前端模块到远程服务器 | 
				
			||||
 | 
					      const register = new RemoteFrontEndModuleRegister(devServer); | 
				
			||||
 | 
					      // 延后 5 秒执行, 且每 5 秒执行一次 | 
				
			||||
 | 
					      register.regist(5000,5000); | 
				
			||||
 | 
					      return middlewares; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					  }, | 
				
			||||
 | 
					}); | 
				
			||||
					Loading…
					
					
				
		Reference in new issue