本文参加了由公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
【若川视野 x 源码共读】第13期 | open 打开浏览器 点击了解本期详情一起参与。
平时使用vue脚手架和vite启动项目后可自动打开浏览器,
vue脚手架配置如下:
module.exports = {
//...
devServer: {
open: true,
},
};
vite配置如下:
export default defineConfig({
//...
server: {
open: true,
},
})
一、学习目标😀
1、了解open库原理。
统、process进程、child_process子进程模块。
3、使用vscode调试代码。
二、源码调试😊
1、open库地址:github.com/sindresorhu…
git clone https://github.com/sindresorhus/open.git
cd open目录
npm i
2、自己跟着源码实现了open功能,并且加了相应注释,更容易理解。
const childProcess = require('child_process');
const isWsl = require('is-wsl');
//WSL是一种允许在Windows操作系统上运行Linux应用程序的兼容层,因此在WSL环境下运行的Node.js进程可能需要特殊处理
const isDocker = require('is-docker'); //检测Node.js进程是否运行在Docker容器
const { platform, arch } = process;
const { promises: fs, constants: fsConstants } = require('fs');
// 一、传参,检查类型
const open = (target, options) => {
if (typeof target !== 'string') {
throw new TypeError('Expected a `target`');
}
return baseOpen({
...options,
target,
});
};
// 二、开始baseOpen
const baseOpen = async options => {
options = {
wait: false,
background: false,
newInstance: false,
allowNonzeroExitCode: false,
...options,
};
let { name: app, arguments: appArguments = [] } = options.app || {};
appArguments = [...appArguments];
// 命令行&参数解析
let command; // 调用系统dos窗口
const cliArguments = [];
const childProcessOptions = {};
// 系统环境兼容,这里只展示window系统代码
if (platform === 'win32' || (isWsl && !isDocker())) {
// mountPoint = '/mnt/'
const mountPoint = await getWslDrivesMountPoint();
// 四、getWslDrivesMountPoint结束
command = isWsl
? `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`
: `${process.env.SYSTEMROOT}\System32\WindowsPowerShell\v1.0\powershell`;
// process.env.SYSTEMROOT获取进程环境变量,
// Windows PowerShell启动进程的参数
// -NoProfile: 不加载PowerShell的个人资料文件。
// -NonInteractive: 以非交互方式运行PowerShell(即不需要用户输入)。
// -ExecutionPolicy: 设置脚本执行策略。
// Bypass: 跳过所有策略限制。
// -EncodedCommand: 指示要在命令行中传递Base64编码的PowerShell命令。
// -WindowStyle: 设定窗口的样式,如:Normal, Hidden , Minimized ,Maximi
cliArguments.push('-NoProfile', '-NonInteractive', '–ExecutionPolicy', 'Bypass', '-EncodedCommand');
if (!isWsl) {
// windowsVerbatimArguments是在 Windows 上不为参数加上引号或转义
childProcessOptions.windowsVerbatimArguments = true;
}
const encodedArguments = ['Start'];
if (options.wait) {
encodedArguments.push('-Wait');
}
if (options.target) {
encodedArguments.push(`"${options.target}"`);
}
// 使用PowerShell接受的Base64编码命令来允许特殊字符。
options.target = Buffer.from(encodedArguments.join(' '), 'utf16le').toString('base64');
}
if (options.target) {
cliArguments.push(options.target);
}
const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
console.log(subprocess, command, 'subprocess');
subprocess.unref();
return subprocess;
};
// 三、getWslDrivesMountPoint开始
const getWslDrivesMountPoint = (() => {
const defaultMountPoint = '/mnt/';
let mountPoint;
return async function () {
if (mountPoint) {
return mountPoint;
}
const configFilePath = '/etc/wsl.conf';
let isConfigFileExists = false;
try {
// windows下以下try catch没执行, 疑问?
// configFilePath文件访问权限,fs.constants.X_OK: 检查文件是否可执行
let res = await fs.access(configFilePath, fsConstants.F_OK);
isConfigFileExists = true;
console.log(res, 'res');
// windows下以下try catch没执行, 疑问?
} catch {}
if (!isConfigFileExists) {
return defaultMountPoint;
}
};
})();
module.exports = open;
3、创建test.js文件,调用open方法
open('https://www.baidu.com/');
文件夹目录😁
4、在open路径下,终端执行命令:
node test.js
三、vscode调试node代码😊
1、在行首打断点
2、点击运行调试
选择Node.js
点击单步调试
四、小结
1、is-wsl 包:用于检测当前Node.js进程是否运行在Windows Subsystem for Linux(WSL)环境下的npm模块。WSL是一种允许在Windows操作系统上运行Linux应用程序的兼容层,因此在WSL环境下运行的Node.js进程可能需要特殊处理。
2、process进程:
process.argv属性来获取当前进程的命令行参数数组。
process.env属性来获取当前进程的环境变量。
process.cwd() 方法可以返回当前工作目录的路径。
process.exit() 方法则可以用于在任何时候退出当前进程。
process对象还提供了事件机制,您可以监听特定事件(如exit事件)以执行自定义操作。process.on(eventName, callback) 方法,您可以注册事件处理程序函数来响应不同的进程事件。
process.arch获取操作系统 CPU 架构
process.platform返回操作系统平台
3、fs文件系统
fs.access(path[, mode], callback) 测试用户对 path 指定的文件或目录的权限
fs.fsConstants提供了文件系统相关的一些常量。这些常量包括文件打开和操作模式、文件访问权限等。
在使用fs模块进行文件系统操作时,可以使用fsConstants模块中定义的常量,例如:
- fs.constants.F_OK: 检查文件是否存在
- fs.constants.R_OK: 检查文件是否可读
- fs.constants.W_OK: 检查文件是否可写
- fs.constants.X_OK: 检查文件是否可执行
- fs.constants.O_RDONLY: 只读模式打开文件
- fs.constants.O_WRONLY: 只写模式打开文件
- fs.constants.O_RDWR: 读写模式打开文件
4、child_process 子进程
child_process.spawn(command[, args][, options]) 是Node创建新进程的方法之一。