【webpack】动态配置cdn,多模板入口项目搭建

news2024/12/24 11:39:47

动态配置多模板

  1. 按照这个模板创建项目
    在这里插入图片描述

  2. 安装glob,获取目录下的文件名称

  3. 封装方法utilsConfig,动态生产 page

    // pages 多入口配置
    const path = require("path");
    
    // glob 是 webpack 安装时依赖的一个第三方模块,该模块允许你使用 * 等符号,
    // 例如 lib/*.js 就是获取 lib 文件夹下的所有 js 后缀名的文件
    const glob = require("glob");
    
    // 取得相应的页面路径,因为之前的配置,所以是 src 文件夹下的 pages 文件夹
    const PAGE_PATH = path.resolve(__dirname, "./src/pages");
    
    exports.setPages = (value = "") => {
      let entryFiles = glob.sync(PAGE_PATH.replace(/\\/g, "/") + "/*/*.js");
      let map = {};
      entryFiles.forEach((filePathValue) => {
        const filePath = filePathValue.replace(/\\/g, "/");
        let filename = filePath.substring(
          filePath.lastIndexOf("/") + 1,
          filePath.lastIndexOf(".")
        );
        if (value == "" || value == filename) {
          let tmp =
            filePath.substring(0, filePath.lastIndexOf("/")) + `/${filename}`;
          let conf = {
            // page 的入口
            entry: filePath,
            title: "项目名称_" + filename,
            // 模板来源
            // template: "./public/index.html",
            template: tmp + ".html",
            // 在 dist/index.html 的输出
            filename: (value && value != "" ? "index" : filename) + ".html",
            // 页面模板需要加对应的js脚本,如果不加这行则每个页面都会引入所有的js脚本
            chunks: ["manifest", "vendor", filename],
            id: filename,
            inject: true,
          };
          map[filename] = conf;
        }
      });
      return map;
    };
    
  4. 配置vue.config.js

    const { defineConfig } = require("@vue/cli-service");
    const utils = require("./utilsConfig");
    const path = require("path");
    const pagesList = utils.setPages(appid);
    module.exports = defineConfig({
      // 通过appid进行设置对应的pages,传入''则是设置所有的入口和模板全部
      pages: pagesList,
    });
    
  5. ./router/index.js,配置多项目的功能页面

    import { createRouter, createWebHistory } from "vue-router";
    import store from "@/store";
    // 公共页面
    const routesList = [
      {
        path: "/",
        redirect: "/index",
      },
      {
        path: "index",
        name: "index",
        component: () => import("@/views/index.vue"),
      },
      {
        path: "home",
        name: "home",
        component: () => import("@/views/home.vue"),
      },
    ];
    const router = createRouter({
      history: createWebHistory(process.env.BASE_URL),
      routes: [],
    });
    
    // 重写push
    const originalPush = router.push;
    router.push = function push(valueData) {
      const routerList = router.getRoutes();
      let routeUrl = router.resolve(valueData);
      if (routerList.findIndex((n) => n.path == routeUrl.path) != -1) {
        return originalPush.call(this, valueData).catch((err) => err);
      } else {
        if (
          routeUrl.href.includes("https://") ||
          routeUrl.href.includes("http://")
        ) {
          let hrefUrl = routeUrl.href;
          const index1 = routeUrl.href.indexOf("https://");
          if (index1 != -1) {
            hrefUrl = hrefUrl.substring(index1);
          }
          const index2 = routeUrl.href.indexOf("http://");
          if (index2 != -1) {
            hrefUrl = hrefUrl.substring(index2);
          }
          window.location.href = hrefUrl;
        } else {
          window.location.href = routeUrl.href;
        }
      }
    };
    // 重写replace
    const originalReplace = router.replace;
    router.replace = function replace(valueData) {
      let routeUrl = router.resolve(valueData);
      const routerList = router.getRoutes();
      if (routerList.findIndex((n) => n.path == routeUrl.path) != -1) {
        return originalReplace.call(this, valueData).catch((err) => err);
      } else {
        if (
          routeUrl.href.includes("https://") ||
          routeUrl.href.includes("http://")
        ) {
          let hrefUrl = routeUrl.href;
          const index1 = routeUrl.href.indexOf("https://");
          if (index1 != -1) {
            hrefUrl = hrefUrl.substring(index1);
          }
          const index2 = routeUrl.href.indexOf("http://");
          if (index2 != -1) {
            hrefUrl = hrefUrl.substring(index2);
          }
          window.location.replace(hrefUrl);
        } else {
          window.location.replace(routeUrl.href);
        }
      }
    };
    
    router.beforeEach((to, from, next) => {
      // 判断是否缓存
      console.log(to, from);
      const keepAlive = to.meta.keepAlive;
      const name = to.name;
      if (keepAlive && !store.state.aliveList.includes(name)) {
        store.dispatch("setAliveList", name);
      }
      next();
    });
    
    export default { router, routesList };
    
  6. ./pages/index1/router/index.js./pages/index2/router/index.js,配置对应多项目的对应路由

    // 单个页面
    const routesList = [
      {
        path: "about",
        name: "about",
        component: () => import("../views/about.vue"),
        meta: {
          keepAlive: true,
        },
      },
      {
        path: "index",
        name: "index",
        component: () => import("../views/index.vue"),
      },
    ];
    
    export default routesList;
    
  7. ./pages/index1/index1.js./pages/index2/index2.js,合并路由

    import { createApp } from "vue";
    import store from "@/store";
    const pageInit = require("@/utils/pageInit");
    pageInit.setInit("index1").then((res) => {
      createApp(res.index).use(store).use(res.router).mount("#app");
    });
    
  8. 合并时需要调用封装的方法pageInit

    /* eslint-disable */
    exports.setInit = async (value) => {
      const indexVue = (await import(`@/pages/${value}/${value}.vue`)).default;
      const routerPageList = (await import(`@/pages/${value}/router`)).default;
      const routerObject = (await import(`@/router`)).default;
      routerObject.router.addRoute({
        path: `/${value}`,
        name: `${value}`,
        component: indexVue,
      });
      routerObject.routesList.forEach((item) => {
        routerObject.router.addRoute(`${value}`, {
          ...item,
          meta: { fromList: "common", ...(item.meta || {}) },
        });
      });
      routerPageList.forEach((item) => {
        routerObject.router.addRoute(`${value}`, {
          ...item,
          meta: { fromList: `${value}`, ...(item.meta || {}) },
        });
      });
      return Promise.resolve({ index: indexVue, router: routerObject.router });
    };
    /* eslint-disable */
    

    此时配置成功后,公共页面路由是这样的/index,对应项目的路由是这样的/index1/about/index2/about

last. 具体文档

  • vue多入口、多模板文档

动态配置 cdn

  1. 安装依赖script-ext-html-webpack-plugin

    npm install script-ext-html-webpack-plugin --save--dev
    
  2. vue.config.js配置

    const { defineConfig } = require("@vue/cli-service");
    const utils = require("./utilsConfig");
    const path = require("path");
    const pagesList = utils.setPages(appid);
    // externals
    const externals = {
      vue: "Vue",
      "vue-router": "VueRouter",
      vuex: "Vuex",
      axios: "axios",
    };
    
    // CDN外链,会插入到对应的.html中
    const cdn = {
      css: [],
      js: [
        "https://unpkg.com/vue@3.2.13/dist/vue.global.js",
        "https://unpkg.com/vue-router@4.0.3/dist/vue-router.global.js",
        "https://unpkg.com/axios/dist/axios.min.js",
        "https://unpkg.com/vuex@4.0.0/dist/vuex.global.js",
      ],
    };
    module.exports = defineConfig({
      configureWebpack: (config) => {
        config.name = "xxx";
        config.externals = externals;
      },
      chainWebpack: (config) => {
        config.plugins.delete("preload"); // TODO: need test
        config.plugins.delete("prefetch"); // TODO: need test
    
        // 别名 alias
        config.resolve.alias
          .set("@", resolve("src"))
          .set("assets", resolve("src/assets"))
          .set("api", resolve("src/api"))
          .set("views", resolve("src/views"))
          .set("components", resolve("src/components"));
    
        // 多入口的
        Object.keys(pagesList).forEach((key) => {
          config.plugin("html-" + key).tap((args) => {
            if (args.length > 0) {
              args[0].title = "项目名称" + key;
              args[0].cdn = cdn;
            }
            return args;
          });
        });
        // 单一的
        // config
        //   .plugin("html-index")
        //   .tap((args) => {
        //     args[0].title = "项目名称";
        //     args[0].cdn = cdn;
        //     return args;
        //   })
      },
    });
    
    • 我们可以通过vue inspect,查看当前项目 webpack 配置,进而知道注入 cdn 模块的名称

      在这里插入图片描述

  3. 模板对应的html

    <!DOCTYPE html>
    <html lang="">
      <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width,initial-scale=1.0" />
        <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
        <title><%= htmlWebpackPlugin.options.title %></title>
        <% for (var i in
        htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
        <link
          href="<%= htmlWebpackPlugin.options.cdn.css[i] %>"
          rel="preload"
          as="style"
        />
        <% } %>
      </head>
    
      <body>
        <noscript>
          <strong
            >We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
            properly without JavaScript enabled. Please enable it to
            continue.</strong
          >
        </noscript>
        <div id="app"></div>
        <% for (var i in
        htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
        <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
        <% } %>
        <!-- built files will be auto injected -->
      </body>
    </html>
    
    • 主要是对 htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js进行循环

通过命令打包不同的文件

  1. 修改 package.json,添加命令

    "scripts": {
       "serve-index1": "vue-cli-service serve --Key=index1 --port 8081",
       "serve-index2": "vue-cli-service serve --Key=index2 --port 8082",
       "build-index1": "vue-cli-service build --Key=index1 ",
       "build-index2": "vue-cli-service build --Key=index2",
        ...
      },
    
  2. 修改vue.config.js

    const { defineConfig } = require("@vue/cli-service");
    // 获取命令的参数
    const argvData = process.argv;
    // 获取appid
    let appid = "";
    argvData.forEach((item) => {
      if (item.includes("--Key=")) {
        appid = item.split("=")[1];
      }
    });
    // 获取outputDir的路径
    const getOutputDir = (value) => {
      if (value == "") {
        return "dist/";
      } else {
        return `dist/${value}`;
      }
    };
    
    module.exports = defineConfig({
      outputDir: getOutputDir(appid),
    });
    
  3. 运行 npm run build-index1npm run build-index2

    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/853525.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图片如何转pdf?几个小妙招了解一下

图片如何转pdf&#xff1f;在日常工作和生活中&#xff0c;我们经常需要将图片转换成PDF格式&#xff0c;以便于我们进行存档、传输或打印。那么&#xff0c;如何快速、方便地将图片转换成PDF呢&#xff1f;这里介绍就为大家介绍几款好用的工具。 我们可以使用【迅捷PDF转换器】…

opencv动态目标检测

文章目录 前言一、效果展示二、实现方法构造形态学操作所需的核:创建背景减除模型:形态学操作:轮廓检测: 三、代码python代码C代码 总结参考文档 前言 很久没更新文章了&#xff0c;这次因为工作场景需要检测动态目标&#xff0c;特此记录一下。 一、效果展示 二、实现方法 基…

简化AD管理减少IT工作负担

管理和保护混合 AD 环境 IT 管理员几乎每天都要创建和管理多个 AD 对象&#xff0c;利用本机AD工具&#xff08;如Active Directory用户和计算机控制台以及PowerShell脚本&#xff09;来执行这些任务并不理想&#xff0c;因为它们必须在多个控制台之间切换才能执行这些任务&am…

【UE4 RTS】02-Camera Movement

前言 本篇实现了CameraPawn的基本移动功能 步骤 1. 打开项目设置&#xff0c;在 引擎——输入 一栏中删除模板自带的操作映射 在轴映射中&#xff0c;删除“TurnRate” 添加如下键值 2. 打开“RTS_PlayerController_BP”&#xff0c;在事件图表中添加如下节点 此时运行游戏就…

MySQL和钉钉单据接口对接

MySQL和钉钉单据接口对接 数据源系统:钉钉 钉钉&#xff08;DingTalk&#xff09;是阿里巴巴集团打造的企业级智能移动办公平台&#xff0c;是数字经济时代的企业组织协同办公和应用开发平台。钉钉将IM即时沟通、钉钉文档、钉闪会、钉盘、Teambition、OA审批、智能人事、钉工牌…

Java后台生成ECharts图片

前言 通过echarts的jar包&#xff0c;Java后台生成一张图片&#xff0c;并把图片插入到word中。关于word插图片的代码在下一章。 需要用到的工具PhantomJS,Echarts-convert.js,jquery.js,echarts.js。 1.PhantomJS 介绍 PhantomJS是一个不需要浏览器的富客户端。 官方介绍&…

PS的一些智能对象是怎么用的?用于包装设计该怎么使用?

大家都对一些效果图不太理解&#xff0c;我现在就献丑给大家讲一下&#xff0c;教程都是网友盛传的&#xff0c;我自己学习并且有所体会。 一般做的非常好的PS效果图都是外国人自己做的&#xff0c;所以大多数效果图都是英文&#xff0c;细心的网友会发现&#xff0c;中文的是一…

IOS上架流程

IOS上架流程 准备 开发者账号完工的项目 上架步骤 一、创建App ID二、创建证书请求文件 &#xff08;CSR文件&#xff09;三、创建发布证书 &#xff08;CER&#xff09;四、创建Provisioning Profiles配置文件 &#xff08;PP文件&#xff09;五、在App Store创建应用六、…

MPLAB X IDE v6.1.0 使用MCC代码配置器

安装教程应该很好搜到&#xff0c;如果没有 代码配置器&#xff08;MPLAB Code Configurator&#xff0c;MCC&#xff09;说明IDE版本太低了&#xff0c;建议更新下版本&#xff1b; 刚安装完成之后第一次启动会很卡&#xff0c;属于正常现象&#xff1b; 我这好像是离线模式…

博客网站添加复制转载提醒弹窗Html代码

网站如果是完全禁止右键&#xff08;复制、另存为等&#xff09;操作&#xff0c;对用户来说体验感会降低&#xff0c;但是又不希望自己的原创内容直接被copy&#xff0c;今天飞飞和你们分享几行复制转载提醒弹窗Html代码。 效果展示&#xff1a; 复制以下代码&#xff0c;将其…

11_Vue3中的新的组件

1. Fragment 在Vue2中&#xff1a;组件必须要有一个跟标签在Vue3中&#xff1a;组件可以没有根标签&#xff0c;内部会将多个标签包含在一个Fragment虚拟元素中好处&#xff1a;减少标签层级&#xff0c;减少内存占用 2. Teleport 什么是Teleport?——Teleport 是一种能够将…

ubuntu22.04源码编译opencv4.6

第一次编译之后&#xff0c;测试opencv_example不成功&#xff0c;又重新卸载了再装了一次&#xff0c;成功了&#xff0c;简单记录一下。 下载opencv4.6以及opencv_contrib-4.6.0 opencv下载地址 opencv-contrib下载地址解压以后&#xff0c;把contrib放到opencv4.6文件夹下 第…

无涯教程-Perl - getnetent函数

描述 此函数从/etc/networks文件获取下一个条目,返回-($name,$aliases,$addrtype,$net) 如果/etc/networks文件为空,则它将不返回任何内容,并且调用将失败。 语法 以下是此函数的简单语法- getnetent返回值 此函数在错误时返回undef,否则在标量context中返回网络地址,在错…

Qt应用开发(基础篇)——框架类 QFrame

一、前言 QFrame继承于QWidget&#xff0c;被QLCDNumber、QToolBox、QLabel、QListView等部件继承&#xff0c;是一个拥有矩形框架的基类。 QFrame可以直接创建成一个没有内容的的矩形框架&#xff0c;框架的样式由边框厚度(lineWidth)、框架形状(QFrame::Shape)和阴影样式(QFr…

药物临床试验项目风险管理︱科济生物医药临床运营部总监张立峰

科济生物医药&#xff08;上海&#xff09;有限公司临床运营部总监张立峰先生受邀为由PMO评论主办的2023第十二届中国PMO大会演讲嘉宾&#xff0c;演讲议题&#xff1a;药物临床试验项目风险管理---回顾疫情考验下的风险管理应对。大会将于8月12-13日在北京举办&#xff0c;敬请…

小程序外包开发框架

小程序是一种轻量级的移动应用程序&#xff0c;通常用于在微信和其他平台上提供简单的交互和功能。以下是一些常见的小程序开发框架以及它们的特点&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.微…

冯诺依曼体系结构与进程概念理解

目录 1. 先谈硬件 1、初步理解冯诺依曼体系结构 2、理解各个模块之间的协作 2. 再谈软件 1、为什么要有操作系统 2、操作系统如何管理软硬件资源 3. 再谈进程 1、什么是进程 2、如何理解进程 3、Linux 是如何管理进程的 写在最后&#xff1a; 1. 先谈硬件 1、初步理…

亚马逊对AIGC的定义

大家好&#xff0c;这里是Doker,最近AIGC非常火&#xff0c;这里我们聊一下什么是AIGC. 一、 AIGC 介绍与典型行业应用场景 ​AIGC 又称生成式 AI (Generative AI)&#xff0c;是继专业生产内容&#xff08;PGC&#xff0c; Professional-generated Content&#xff09;、用户…

谁知道,多项目管理的进度管理应该如何进行?

大家好&#xff0c;我是老原。多项目管理的进度管理应该如何进行&#xff1f; 我们应该拆分开来看&#xff1a;一手应对多项目管理&#xff0c;一手把握进度管控。 这个和一个人同时需要处理/负责多个项目线程&#xff0c;道理上是通用的。 今天还是会一如即往的在文章里给大…

7.5 批量规范化详解

BatchNorm(归一化/标准化) 归一化/标准化实质是一种线性变换&#xff0c;线性变换有很多良好的性质&#xff0c;这些性质决定了对数据改变后不会造成“失效”&#xff0c;反而能提高数据的表现&#xff0c;这些性质是归一化/标准化的前提。比如有一个很重要的性质&#xff1a;…