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