背景:由于中台项目页面繁多,文件夹繁多,开发人员每次修改页面都要根据路由路径去找对应的源代码,所以,有没有一种方法,可以直接在开发环境运行的页面里面直接定位到vscode源代码
原理:通过vscode protocal 协议方式(vscode://file/文件路径:行号),去唤起vscode查看源文件了。
1、以vue-admin-template为例子
# clone the project
git clone https://github.com/PanJiaChen/vue-admin-template.git
# enter the project directory
cd vue-admin-template
# install dependency
npm install
# develop
npm run dev
2、安装插件webpack-virtual-modules
npm i webpack-virtual-modules -D
3、修改vue.config.js文件
// vue.config.js
// 添加以下代码
// 借助webpack-virtual-modules生成虚拟模块
const VirtualModulesPlugin = require('webpack-virtual-modules')
configureWebpack: config => {
const plugins = []
if (process.env.NODE_ENV === 'development') {
plugins.push(
/** 创建虚拟模块 */
new VirtualModulesPlugin({
'node_modules/virtual-module-cwd.js': `module.exports = "${process.cwd().replace(/\\/g, '/')}"`
})
)
}
config.plugins = [...config.plugins, ...plugins]
}
4、在src/utils/
文件夹下创建文件vscodeRouterFile.js
,内容如下:
const cwd = require("virtual-module-cwd");
export default {
install(Vue, options = {}) {
const { style = {}, innerHTML = "" } = options;
function createDom(path) {
const domId = "vscode_router_file_element";
let dom = document.querySelector(`#${domId}`);
if (!dom) {
dom = document.createElement("div");
dom.id = domId;
Object.assign(
dom.style,
{
position: "fixed",
fontWeight: "bold",
top: "200px",
right: "50px",
zIndex: 10000,
cursor: "move",
width: "70px",
height: "70px",
borderRadius: "50%",
lineHeight: "70px",
textAlign: "center",
fontSize: "14px",
color: "rgb(255, 255, 255)",
userSelect: "none",
backgroundImage: "linear-gradient(to right, red,orange,yellow,green,blue,indigo,violet)"
},
style
);
dom.innerHTML = innerHTML || "打开源码";
document.body.appendChild(dom);
dragDom(dom);
}
dom.ondblclick = function () {
window.open(`vscode://file/${cwd}/${path}:0`);
};
}
function dragDom(dom) {
let x = 0;
let y = 0;
let l = 0;
let t = 0;
let isDown = false;
dom.onmousedown = function (e) {
x = e.clientX;
y = e.clientY;
l = dom.offsetLeft;
t = dom.offsetTop;
isDown = true;
dom.style.cursor = "move";
};
window.onmousemove = function (e) {
if (isDown === false) return;
const nx = e.clientX;
const ny = e.clientY;
const nl = nx - (x - l);
const nt = ny - (y - t);
dom.style.left = nl + "px";
dom.style.top = nt + "px";
};
dom.onmouseup = function () {
isDown = false;
dom.style.cursor = "default";
};
}
Vue.mixin({
beforeRouteEnter(to, from, next) {
next((vm) => {
const routerCom = to.matched[to.matched.length-1];
if(!routerCom) return
routerCom && createDom(routerCom.components.default.__file);
});
},
});
},
};
5、在mian.js
里面引用
/** 开发环境引入vscodeRouterFile */
import vscodeRouterFile from "@/utils/vscodeRouterFile"
if(process.env.NODE_ENV === 'development') {
Vue.use(vscodeRouterFile)
}
6、运行项目,会出现打开源码
的按钮,双击
可跳转到对应的路由源文件
7、缺点
- 如果vscode有多个实例(窗口)在运行,文件会在焦点实例(窗口)里面打开,建议只开启一个vscode实例(窗口)
8、参考资料
https://juejin.cn/post/6960480138525933599
9、由于并没有引入virtual-module-cwd模块,导致打包const cwd = require("virtual-module-cwd")报错失败,以下为修改后的最新代码
原理:由于webpack设置了开发环境才生成虚拟模块,在打包时没有虚拟模块,当前代码const cwd = require("virtual-module-cwd")
引入失败,由于es6模块
加载不能在代码块里面引用,所以改为node模块
引用,这样就可以先判断当前运行环境,再引入vscodeRouterFile代码
// main.js
/** 用于vscode根据路由定位源文件 */
if (process.env.NODE_ENV === 'development') {
const { install } = require('../vscodeRouterFile')
Vue.use({install})
}
// vscodeRouterFile\index.js
const cwd = require("virtual-module-cwd");
export function install(Vue, options = {}) {
const { style = {}, innerHTML = "" } = options;
function createDom(path) {
const domId = "vscode_router_file_element";
let dom = document.querySelector(`#${domId}`);
if (!dom) {
dom = document.createElement("div");
dom.id = domId;
Object.assign(
dom.style,
{
position: "fixed",
fontWeight: "bold",
top: "200px",
right: "50px",
zIndex: 10000,
cursor: "move",
width: "70px",
height: "70px",
borderRadius: "50%",
lineHeight: "70px",
textAlign: "center",
fontSize: "14px",
color: "rgb(255, 255, 255)",
userSelect: "none",
background: "lightgray",
textShadow: "4px 4px 4px #000000"
},
style
);
dom.innerHTML = innerHTML || "打开源码";
document.body.appendChild(dom);
dragDom(dom);
}
dom.ondblclick = function () {
window.open(`vscode://file/${cwd}/${path}:0`);
};
}
function dragDom(dom) {
let x = 0;
let y = 0;
let l = 0;
let t = 0;
let isDown = false;
dom.onmousedown = function (e) {
x = e.clientX;
y = e.clientY;
l = dom.offsetLeft;
t = dom.offsetTop;
isDown = true;
dom.style.cursor = "move";
};
window.onmousemove = function (e) {
if (isDown === false) return;
const nx = e.clientX;
const ny = e.clientY;
const nl = nx - (x - l);
const nt = ny - (y - t);
dom.style.left = nl + "px";
dom.style.top = nt + "px";
};
dom.onmouseup = function () {
isDown = false;
dom.style.cursor = "default";
};
}
Vue.mixin({
beforeRouteEnter(to, from, next) {
next(async (vm) => {
const routerCom = to.matched[to.matched.length - 1];
if (!routerCom) return
routerCom && createDom(routerCom.components.default.__file);
});
},
});
}