项目(Vue2.7)最近要部署到外网,所以一些内网使用的资源文件需要根据发布内容进行更换或者删除,最初为了临时解决外网部署问题写了一版很low的方案,具体代码如下:
<!-- index.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>
<script src="<%= BASE_URL %>lib.min.js" type="text/javascript"></script>
<link ignore rel="stylesheet" id="wicCss" rel="prefetch"
href="<%= !JSON.parse(VUE_APP_OTAF_FLAG) ? '/wic-uportal/comps/wic-comps.css' : '' %>" />
<script src="" type="text/javascript"></script>
<script id="rdcLib"
src="<%= !JSON.parse(VUE_APP_OTAF_FLAG) ? '/zte-rdcloud-rdc-libuportal/rdc-component/lib.min.js' : '' %>"
type="text/javascript"></script>
<script id="wicLib" src="<%= !JSON.parse(VUE_APP_OTAF_FLAG) ? '/wic-uportal/comps/wic-comps.umd.min.js' : '' %>"
type="text/javascript"></script>
<script ignore
src="<%= JSON.parse(VUE_APP_OTAF_FLAG) ? '/iui/component/thirdparty/jquery/jquery.min.js' : '' %>"></script>
<script ignore src="<%= JSON.parse(VUE_APP_OTAF_FLAG) ? '/iui/component/common/js/tools.min.js' : '' %>"></script>
</head>
<body>
<div id="xxapp-wm"></div> <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>
</body>
</html>
其中VUE_APP_OTAF_FLAG是区分内外网的一个标识字段,定义在环境变量中的。
这种写法会导致打包之后存在src为空的script和href为空的link标签。所以趁着业务开发间隙改良了一版,奖cdn的内容在vue.config.js中进行引用注入,具体如下:
<!-- index.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>
<% if(htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css){ %>
<% for(var css of htmlWebpackPlugin.options.cdn.css){ %>
<link rel="stylesheet" href="<%= css %>" />
<% } %>
<% } %>
<% if(htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js){ %>
<% for(var js of htmlWebpackPlugin.options.cdn.js){ %>
<script src="<%= js %>"></script>
<% } %>
<% } %>
</head>
<body>
<div id="xxapp-wm"></div>
<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>
</body>
</html>
//vue.config.js
const isOtaf = JSON.parse(process.env.VUE_APP_OTAF_FLAG)
const cdn = isOtaf ? {
js: [`${process.env.BASE_URL}/lib.min.js`, "/iui/component/thirdparty/jquery/jquery.min.js", "/iui/component/common/js/tools.min.js"],
css: [],
} : {
js: [,"/zte-rdcloud-rdc-libuportal/rdc-component/lib.min.js", "/wic-uportal/comps/wic-comps.umd.min.js"],
css: ["/wic-uportal/comps/wic-comps.css"],
};
chainWebpack: config => {
config
.plugin('html')
.tap(args => {
args[0].title = 'RAG Studio';
args[0].cdn = cdn;
return args
})
},
其实写到这种程度已经解决了空地址引用的问题,但是为了尽量简洁index.html文件中的代码,将功能从vue.config.js中剥离出来,同时又可以给组内前端小伙伴一个封装Webpack插件的具象化示例,最终还是决定将cdn注入使用插件的方式完成,所以又进行了一次优化,封装了一个webpack插件,完成资源的引用注入。
插件代码:
// injectCdnPlugin.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
class InjectCdnPlugin {
constructor (options) {
this.options = options;
this.pluginName = 'InjectCdnPlugin';
}
apply (compiler) {
const pluginName = this.pluginName; // 使用pluginName
compiler.hooks.compilation.tap(pluginName, compilation => {
HtmlWebpackPlugin.getHooks(compilation).alterAssetTags.tap(
pluginName,
data => {
// 确保scriptTag和linkTag都是数组
if (!Array.isArray(data.assetTags.scripts)) {
data.assetTags.scripts = [];
}
if (!Array.isArray(data.assetTags.styles)) {
data.assetTags.styles = [];
}
// 添加额外的script标签
const scriptTag = data.assetTags.scripts;
// console.log(data.assetTags)
this.options.js.forEach(scriptEntry => {
scriptTag.unshift({
tagName: 'script',
voidTag: false,
meta: { plugin: pluginName },
attributes: {
src: scriptEntry.src || scriptEntry
}
});
});
// 额外添加link标签来引入CSS
const linkTag = data.assetTags.styles;
this.options.css.forEach(cssEntry => {
linkTag.unshift({
tagName: 'link',
voidTag: true, // link标签是void标签,没有结束标签
meta: { plugin: pluginName },
attributes: {
rel: 'stylesheet',
type: 'text/css',
href: cssEntry.href || cssEntry // 假设你的css对象有href属性
}
});
});
}
);
});
}
}
module.exports = InjectCdnPlugin;
创建插件实例:
// injectCdnPluginInstance.js
// 导入InjectCdnPlugin插件
const InjectCdnPlugin = require('./injectCdnPlugin');
// 获取publicPath和isOtaf标志
const publicPath = process.env.BASE_URL;
const isOtaf = JSON.parse(process.env.VUE_APP_OTAF_FLAG);
// 定义CDN资源的URL
const cdnJsUrls = {
otaf: ['/iui/component/common/js/tools.min.js', '/iui/component/thirdparty/jquery/jquery.min.js', `${process.env.BASE_URL}/lib.min.js`],
notOtaf: ['/wic-uportal/comps/wic-comps.umd.min.js', '/zte-rdcloud-rdc-libuportal/rdc-component/lib.min.js', '/iui/component/vue2lib/lib.min.js']
};
const cdnCssUrls = {
otaf: [],
notOtaf: ['/wic-uportal/comps/wic-comps.css']
};
// 根据isOtaf标志选择正确的CDN配置
const cdn = isOtaf ? {
js: cdnJsUrls.otaf,
css: cdnCssUrls.otaf
} : {
js: cdnJsUrls.notOtaf,
css: cdnCssUrls.notOtaf
};
// 创建InjectCdnPlugin实例
const injectCdnPluginInstance = new InjectCdnPlugin(cdn);
// 将插件实例作为模块的默认导出
module.exports = injectCdnPluginInstance;
vue.config.js配置:
//vue.config.js
const injectCdnPluginInstance = require('./src/lib/injectCdnPluginInstance.js');
plugins: [ injectCdnPluginInstance],
使用不同指令进行内外网打包生成的最终index.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">
<link rel="icon" href="/ai/favicon.ico">
<title>RAG Studio</title>
<script src="/iui/component/vue2lib/lib.min.js" type="module"></script>
<script src="/zte-rdcloud-rdc-libuportal/rdc-component/lib.min.js" type="module"></script>
<script src="/wic-uportal/comps/wic-comps.umd.min.js" type="module"></script>
<script defer="defer" type="module" src="/ai/js/chunk-vendors.0f41a209.js"></script>
<script defer="defer" type="module" src="/ai/js/app.e6ae2e39.js"></script>
<link rel="stylesheet" href="/wic-uportal/comps/wic-comps.css">
<link href="/ai/css/app.efcc1ee0.css" rel="stylesheet">
<script src="/iui/component/vue2lib/lib.min.js" nomodule></script>
<script src="/zte-rdcloud-rdc-libuportal/rdc-component/lib.min.js" nomodule></script>
<script src="/wic-uportal/comps/wic-comps.umd.min.js" nomodule></script>
<script defer="defer" src="/ai/js/chunk-vendors-legacy.0f41a209.js" nomodule></script>
<script defer="defer" src="/ai/js/app-legacy.0036262a.js" nomodule></script>
</head>
<body>
<div id="xxapp-wm"></div><noscript><strong>We're sorry but RAG Studio doesn't work properly without JavaScript
enabled. Please enable it to continue.</strong></noscript>
<div id="app"></div>
</body>
</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">
<link rel="icon" href="/aab-portal/favicon.ico">
<title>RAG Studio</title>
<script src="/aab-portal/lib.min.js" type="module"></script>
<script src="/iui/component/thirdparty/jquery/jquery.min.js" type="module"></script>
<script src="/iui/component/common/js/tools.min.js" type="module"></script>
<script defer="defer" type="module" src="/aab-portal/js/chunk-vendors.0f41a209.js"></script>
<script defer="defer" type="module" src="/aab-portal/js/app.1ce80f14.js"></script>
<link href="/aab-portal/css/app.7a2197c6.css" rel="stylesheet">
<script src="/aab-portal/lib.min.js" nomodule></script>
<script src="/iui/component/thirdparty/jquery/jquery.min.js" nomodule></script>
<script src="/iui/component/common/js/tools.min.js" nomodule></script>
<script defer="defer" src="/aab-portal/js/chunk-vendors-legacy.0f41a209.js" nomodule></script>
<script defer="defer" src="/aab-portal/js/app-legacy.6f7641cc.js" nomodule></script>
</head>
<body>
<div id="xxapp-wm"></div><noscript><strong>We're sorry but RAG Studio doesn't work properly without JavaScript
enabled. Please enable it to continue.</strong></noscript>
<div id="app"></div>
</body>
</html>
内外网两个环境部署之后验证正常。