Wakakawa’s reading that 99% of people don’t know vue-DevTools can open component files directly? This article principle revealed: juejin.cn/post/695934… How to install vue-DevTools developed by Yuxi, and why few people know the function of opening files? : juejin. Cn/post / 699428…
Chuan ge recently organized a source code reading activities. I read about 200 lines of source code a week. If you are interested, you can follow his public account, Ruochuan Vision.
To prepare
- Go over Trango’s article. Get your goals straight
- Learning objective: Understand the implementation principle of vue-DevTools open component
Specific operation
Components used
Use of the main launch-editor-Middleware and launch-Editor libraries
launch-editor-middleware
The main purpose of the launch-editor-middleware middleware is to call launch-Editor
The source code calls
// vue3-project/node_modules/@vue/cli-service/lib/commands/serve.js
/ / 46
const launchEditorMiddleware = require('launch-editor-middleware')
/ / 192 rows
before (app, server) {
// launch editor support.
/ / call launchEditorMiddleware
app.use('/__open-in-editor', launchEditorMiddleware(() = > console.log(
`To specify an editor, specify the EDITOR env variable or ` +
`add "editor" field to your Vue project config.\n`
)))
// omit some code...
}
Copy the code
const url = require('url')
const path = require('path')
const launch = require('launch-editor')
// specifiedEditor passes in a function that returns console.log()
module.exports = (specifiedEditor, srcRoot, onErrorCallback) = > {
if (typeof specifiedEditor === 'function') {
onErrorCallback = specifiedEditor// Assign to onErrorCallback
specifiedEditor = undefined
}
if (typeof srcRoot === 'function') {
onErrorCallback = srcRoot
srcRoot = undefined
}
// srcRoot is the parameter passed in, or the directory of the current Node process
srcRoot = srcRoot || process.cwd()
// Returns the middleware function
return function launchEditorMiddleware (req, res, next) {
const { file } = url.parse(req.url, true).query || {}
if(! file) { res.statusCode =500
res.end(`launch-editor-middleware: required query param "file" is missing.`)}else {
// Join the path using launch
launch(path.resolve(srcRoot, file), specifiedEditor, onErrorCallback)
res.end()
}
}
}
Copy the code
To break point debugging, click the red dot to the left and stop at the breakpoint when the file comes in is clicked
launch-editor
But resolve resolves the path and enters the launchEditor function
// vue3-project/node_modules/launch-editor/index.js
function launchEditor (file, specifiedEditor, onErrorCallback) {
// Parse the file path
const parsed = parseFile(file)
let { fileName } = parsed
const { lineNumber, columnNumber } = parsed
// Check whether the file exists
if(! fs.existsSync(fileName)) {return
}
if (typeof specifiedEditor === 'function') {
onErrorCallback = specifiedEditor
specifiedEditor = undefined
}
onErrorCallback = wrapErrorCallback(onErrorCallback)
// Editor gets the compiler's parameters
const [editor, ...args] = guessEditor(specifiedEditor)
if(! editor) { onErrorCallback(fileName,null)
return
}
// ...
Child_process is a module of Node.js that provides the ability to spawn child processes. By default, stdin, stdout, and stderr pipes are created between the parent node.js process and the spawned child.
if (process.platform === 'win32') {
// On Windows, launch the editor in a shell because spawn can only
// launch .exe files.
// Use the editor command to open the file
_childProcess = childProcess.spawn(
'cmd.exe'['/C', editor].concat(args),
{ stdio: 'inherit'})}else {
_childProcess = childProcess.spawn(editor, args, { stdio: 'inherit' })
}
_childProcess.on('exit'.function (errorCode) {
_childProcess = null
if (errorCode) {
onErrorCallback(fileName, '(code ' + errorCode + ') ')
}
})
_childProcess.on('error'.function (error) {
onErrorCallback(fileName, error.message)
})
}
Copy the code
guessEditor
This function does four things:
- If an editor is specified, the parser returns.
- Find out which editor is running in the current process. MacOS and Linux use ps x and Windows use get-process
- If none is found, use process.env.VISUAL or process.env.Editor. This is why the initial error prompts you to specify the editor using an environment variable.
- If [null] is returned, an error is reported.
GuessEditor deconstructs the parameter display after the assignment
function guessEditor (specifiedEditor) {
if (specifiedEditor) {
return shellQuote.parse(specifiedEditor)
}
// We can find out which editor is currently running by:
// `ps x` on macOS and Linux
// `Get-Process` on Windows
try {
// Determine the platform
if (process.platform === 'darwin') {
const output = childProcess.execSync('ps x').toString()
const processNames = Object.keys(COMMON_EDITORS_OSX)
for (let i = 0; i < processNames.length; i++) {
const processName = processNames[i]
if(output.indexOf(processName) ! = = -1) {
return [COMMON_EDITORS_OSX[processName]]
}
}
} else if (process.platform === 'win32') {
const output = childProcess
.execSync('powershell -Command "Get-Process | Select-Object Path"', {
stdio: ['pipe'.'pipe'.'ignore']
})
.toString()
const runningProcesses = output.split('\r\n')
for (let i = 0; i < runningProcesses.length; i++) {
// `Get-Process` sometimes returns empty lines
if(! runningProcesses[i]) {continue
}
const fullProcessPath = runningProcesses[i].trim()
const shortProcessName = path.basename(fullProcessPath)
if(COMMON_EDITORS_WIN.indexOf(shortProcessName) ! = = -1) {
return [fullProcessPath]
}
}
} else if (process.platform === 'linux') {
// --no-heading No header line
// x List all processes owned by you
// -o comm Need only names column
const output = childProcess
.execSync('ps x --no-heading -o comm --sort=comm')
.toString()
const processNames = Object.keys(COMMON_EDITORS_LINUX)
for (let i = 0; i < processNames.length; i++) {
const processName = processNames[i]
if(output.indexOf(processName) ! = = -1) {
return [COMMON_EDITORS_LINUX[processName]]
}
}
}
} catch (error) {
// Ignore...
}
// Last resort, use old skool env vars
if (process.env.VISUAL) {
return [process.env.VISUAL]
} else if (process.env.EDITOR) {
return [process.env.EDITOR]
}
return [null]}Copy the code
conclusion
- Vue-devtool is able to open files through the code command
code /path/file
Copy the code
- Use node childProcess to run commands. Learn how to use childProcess
- The main steps are divided into two steps:
1. Click open to enter launch middleware 2. Parse relevant paths 3. Use childProcess to start the childProcess and use CMD to run the code command to open the path fileCopy the code