1 Introduction
Hello, my name is , WeChat search Vision" 160a0d7943d258 Follow me, focus on front-end technology sharing, a vision is to help the front-end to broaden its horizons to the forefront of the public account within 5 years. Welcome to add me on WeChatruochuan12
for long-term exchange and learning.This is the launch-editor source code (
9) of the 160a0d7943d2ea learning source code overall architecture series. Learning Source overall architecture series ( What are the must-see JS library ): jQuery , Underscore , lodash , Sentry , vuex , Axios , KOA , Redux . The term “overall architecture” seems a bit big. Let’s say it is the overall structure of the source code. The main thing is to learn the overall structure of the code, and not to delve into the implementation of other specific functions that are not the main line. This article learns the code of the actual warehouse. The next article should be " learn the overall architecture of Vuex 4 source code, and understand its principles and provide/inject principles ".
warehouse address of this article is :
git clone https://github.com/lxchuan12/open-in-editor.git
, the best way to read this article, clone the warehouse and debug by yourself, easy to absorb and digest.If someone talks about how to read the source code, if you are reading the article, you can recommend my source code series article, it is really not reporting 160a0d7943d338.
My article is written as far as possible so that readers who want to read the source code but don't know how to read it can understand. I always recommend using build the environment breakpoint debugging source code to learn , where does not point , watching while debugging, instead of just looking at . As the goes: 160a0d7943d364 It is better to teach people to fish than to teach people to fish .
After reading this article, you will learn:
- How to solve the error of this function
- How to debug learning source code
launch-editor-middleware、launch-editor
and other realization principles
1.1 Scenarios where the source file corresponding to the page cannot be found for a short time
I don’t know if you have encountered such a scene. When you open a page developed by yourself (or your colleague), it is difficult to find the corresponding source file in a short time.
At this time, you may want to have click the page button to automatically use the editor to open the corresponding file function, that would be great.
And vue-devtools
provides such a function, maybe you don't know. I don’t think a lot of people know it, because many people don’t use vue-devtools
.
You may ask, I don’t use vue
. I use react
Is there a similar function? Yes, please see react-dev-inspector . You might also ask, what editor supports Yeah, mainstream vscode、webstorm、atom、sublime
are all supported, you can see more this list Editors Supported .
This article is based on learning the launch-editor source code, which knowing it, knowing why , and exploring the vue-devtools
"open component in editor" function.
1.2 Briefly describe its principle in one sentence
code path/to/file
Briefly describe the principle in one sentence: using nodejs
in child_process
, execute a code path/to/file
, and then the corresponding editor opens the corresponding file, and the corresponding editor executes ps x
in the process ( Window
uses Get-Process
command 060a0d7943d53d) Of course, you can also specify the editor yourself.
1.3 The error resolution of the component that cannot be opened when the editor is opened
When you actually use this function, you may encounter an error saying that the file cannot be opened.
Could not open App.vue in the editor.
To specify an editor, specify the EDITOR env variable or add "editor" field to your Vue project config.
Here is a description of theWindows
computer,VSCode
editor, and terminal tools usedUbuntu
At the same time, I recommend my article Use ohmyzsh to create efficient terminal command line tool windows, ubuntu, mac systems, used .
solution to 160a0d7943d5fe is also simple, which is the English meaning of .
1.3.1 Method 1: First make sure that the editor you use can be opened with a command in the terminal. The article takes VSCode
as an example
If your command line itself cannot run code
such as 060a0d7943d658 to open the editor, it must be an error. At this time, you need to VSCode
into the command line terminal.
The injection method is also simple. A small partner in my communication group provided a screenshot of mac
mac
computer is VSCode
command + shift + p
, Windows
is ctrl + shift + p
. Then enter shell
and choose to install code
. As shown below:
So you can open VSCode
in the terminal.
If you can open it in the terminal and use the command editor to open it, but it still reports an error, then there is a high probability that your editor is not recognized.
Then you can set the designated editor through method two.
1.3.2 Method 2: Specify the editor, specify the editor in the environment variable
In vue
project, the corresponding article is: vue3-project
, add the .env.delelopment
file, and its content is EDITOR=code
. highlights here under my vue-cli
version 4.5.12
, as if vue-cli 3.5
above and only supports custom EDITOR
this environment variable .
# .env.development
# 当然,我的命令行终端已经有了code这个命令。
EDITOR=code
There is no need to specify the corresponding path of the editor (c/Users/lxchu/AppData/Local/Programs/Microsoft VS Code/bin/code
), because an error will be reported. Why do I get an error, because I read the source code and tried it. Because it will be truncated according to the space and becomec/Users/lxchu/AppData/Local/Programs/Microsoft
, of course an error will be reported.
It is also possible that your editor path has a Chinese path and an error is reported. You can add your editor path to the environment variable.
If you pass the above methods, the error reporting problem has not been resolved. Welcome to leave a message, or add me to ruochuan12
communicate. After all, the computer environment is different, it is difficult to ensure that everyone can perform normally, but we know the principle, it is easy to solve the problem .
Next, we explore the implementation principle of the "open component in editor" function from the source code point of view.
2. vue-devtools Open component in editor document
Before exploring the principle, let's take a look at the official document of vue-devtools
vuejs/vue-devtools
Documentation
Open component in editor
To enable this feature, follow this guide.
This guide writes that Vue CLI 3
is out of the box in .
Vue CLI 3 supports this feature out-of-the-box when running vue-cli-service serve.
It also wrote in detail how to use Webpack
# 1. Import the package:
var openInEditor = require('launch-editor-middleware')
# 2. In the devServer option, register the /__open-in-editor HTTP route:
devServer: {
before (app) {
app.use('/__open-in-editor', openInEditor())
}
}
# 3. The editor to launch is guessed. You can also specify the editor app with the editor option. See the supported editors list.
# 用哪个编辑器打开会自动猜测。你也可以具体指明编辑器。这里显示更多的支持编辑器列表
openInEditor('code')
# 4. You can now click on the name of the component in the Component inspector pane (if the devtools knows about its file source, a tooltip will appear).
# 如果`vue-devtools`开发者工具有提示点击的组件的显示具体路径,那么你可以在编辑器打开。
It also wrote how to use Node.js
Node.js
You can use the launch-editor package to setup an HTTP route with the/__open-in-editor
path. It will receive file as an URL variable.
For more information, see this guide .
3. Environmental preparation
Readers who are familiar with me all know that I am recommended for debugging to look at the source code , as the goes: 160a0d7943d975 does not point where . And debugging is generally written in great detail, hoping to help some people know how to read the source code. So I specially built a new warehouse open-in-editor git clone https://github.com/lxchuan12/open-in-editor.git
for everyone to clone and learn.
Install vue-cli
npm install -g @vue/cli
# OR
yarn global add @vue/cli
node -V
# v14.16.0
vue -V
# @vue/cli 4.5.12
vue create vue3-project
# 这里选择的是vue3、vue2也是一样的。
# Please pick a preset: Default (Vue 3 Preview) ([Vue 3] babel, eslint)
npm install
# OR
yarn install
Here also explain my version of vscode.
code -v
1.55.2
Vue CLI 3
mentioned above, 160a0d7943d9dc can be out of the box and Webpack
.
vue3-project/package.json
has a debug
button.
Select the first item, serve vue-cli-service serve
.
Let's search for 'launch-editor-middleware'
. Generally speaking node_modules
cannot be searched, and need to be set. Of course there is also a simple way. That is, there is a setting icon on the right side of "Excluded files" "Use "Troubleshooting settings" and "Ignore files"", click down.
I won’t repeat the rest. You can read this answer: 160a0d7943da40 How to set vscode to search for files contained in node_modules?
At this time, this middleware vue3-project/node_modules/@vue/cli-service/lib/commands/serve.js
As shown below:
4. vue-devtools out of the box with specific source code implementation
Next, let's look at the specific source code implementation Vue CLI 3
out of the box.
// vue3-project/node_modules/@vue/cli-service/lib/commands/serve.js
// 46行
const launchEditorMiddleware = require('launch-editor-middleware')
// 192行
before (app, server) {
// launch editor support.
// this works with vue-devtools & @vue/cli-overlay
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`
)))
// 省略若干代码...
}
When you click on vue-devtools
, there will be a request, http://localhost:8080/__open-in-editor?file=src/App.vue
, and the component will be opened without accident.
Then we implemented launchEditorMiddleware
5. launch-editor-middleware
When looking at the source code, first look at the debug screenshot.
The role in the launch-editor-middleware
middleware is to finally call launch-editor
open the file.
// vue3-project/node_modules/launch-editor-middleware/index.js
const url = require('url')
const path = require('path')
const launch = require('launch-editor')
module.exports = (specifiedEditor, srcRoot, onErrorCallback) => {
// specifiedEditor => 这里传递过来的则是 () => console.log() 函数
// 所以和 onErrorCallback 切换下,把它赋值给错误回调函数
if (typeof specifiedEditor === 'function') {
onErrorCallback = specifiedEditor
specifiedEditor = undefined
}
// 如果第二个参数是函数,同样把它赋值给错误回调函数
// 这里传递过来的是undefined
if (typeof srcRoot === 'function') {
onErrorCallback = srcRoot
srcRoot = undefined
}
// srcRoot 是传递过来的参数,或者当前node进程的目录
srcRoot = srcRoot || process.cwd()
// 最后返回一个函数, express 中间件
return function launchEditorMiddleware (req, res, next) {
// 省略 ...
}
}
previous paragraph of 160a0d7943db71, this way of switching parameters is very common in many source codes. In order to facilitate the user to pass parameters when calling. Although there are multiple parameters, one or two can be passed.
You can set a breakpoint according to the situation. For example, here I will break launch(path.resolve(srcRoot, file), specifiedEditor, onErrorCallback)
// vue3-project/node_modules/launch-editor-middleware/index.js
module.exports = (specifiedEditor, srcRoot, onErrorCallback) => {
// 省略上半部分
return function launchEditorMiddleware (req, res, next) {
// 根据请求解析出file路径
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 {
// 否则拼接路径,用launch打开。
launch(path.resolve(srcRoot, file), specifiedEditor, onErrorCallback)
res.end()
}
}
}
6. launch-editor
Following the breakpoints, I came to the launchEditor
function.
// vue3-project/node_modules/launch-editor/index.js
function launchEditor (file, specifiedEditor, onErrorCallback) {
// 解析出文件路径和行号列号等信息
const parsed = parseFile(file)
let { fileName } = parsed
const { lineNumber, columnNumber } = parsed
// 判断文件是否存在,不存在,直接返回。
if (!fs.existsSync(fileName)) {
return
}
// 所以和 onErrorCallback 切换下,把它赋值给错误回调函数
if (typeof specifiedEditor === 'function') {
onErrorCallback = specifiedEditor
specifiedEditor = undefined
}
// 包裹一层函数
onErrorCallback = wrapErrorCallback(onErrorCallback)
// 猜测当前进程运行的是哪个编辑器
const [editor, ...args] = guessEditor(specifiedEditor)
if (!editor) {
onErrorCallback(fileName, null)
return
}
// 省略剩余部分,后文再讲述...
}
6.1 wrapErrorCallback wrap error function callback
onErrorCallback = wrapErrorCallback(onErrorCallback)
This code is to pass the error callback function, wrapErrorCallback
returned to a new function, and wrapErrorCallback
executed, onErrorCallback(cb) is executed.
I believe that readers can understand, I come alone to tell, mainly because this form wrapped in many functions in the source code are common .
This is the code position output by the Could not open App.vue in the editor.
at the beginning of the article.
// vue3-project/node_modules/launch-editor/index.js
function wrapErrorCallback (cb) {
return (fileName, errorMessage) => {
console.log()
console.log(
chalk.red('Could not open ' + path.basename(fileName) + ' in the editor.')
)
if (errorMessage) {
if (errorMessage[errorMessage.length - 1] !== '.') {
errorMessage += '.'
}
console.log(
chalk.red('The editor process exited with an error: ' + errorMessage)
)
}
console.log()
if (cb) cb(fileName, errorMessage)
}
}
6.2 guessEditor guess the editor currently in use
This function mainly does the following four things:
- If the editor is specified, it will be parsed and returned.
- Find out which editor is running in the current process.
macOS
andLinux
useps x
command
windows
useGet-Process
command - If none is found, use
process.env.VISUAL
orprocess.env.EDITOR
. This is why the initial error prompts that you can use environment variables to specify the editor. - In the end
[null]
it is not found, and an error will be reported.
const [editor, ...args] = guessEditor(specifiedEditor)
if (!editor) {
onErrorCallback(fileName, null)
return
}
// vue3-project/node_modules/launch-editor/guess.js
const shellQuote = require('shell-quote')
const childProcess = require('child_process')
module.exports = function guessEditor (specifiedEditor) {
// 如果指定了编辑器,则解析一下,这里没有传入。如果自己指定了路径。
// 比如 c/Users/lxchu/AppData/Local/Programs/Microsoft VS Code/bin/code
// 会根据空格切割成 c/Users/lxchu/AppData/Local/Programs/Microsoft
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 {
// 代码有删减
if (process.platform === 'darwin') {
const output = childProcess.execSync('ps x').toString()
// 省略
} else if (process.platform === 'win32') {
const output = childProcess
.execSync('powershell -Command "Get-Process | Select-Object Path"', {
stdio: ['pipe', 'pipe', 'ignore']
})
.toString()
// 省略
} else if (process.platform === 'linux') {
const output = childProcess
.execSync('ps x --no-heading -o comm --sort=comm')
.toString()
}
} 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]
}
After reading the guessEditor function, let's look launch-editor
rest of 060a0d7943dd60.
6.3 The rest of launch-editor
You don't need to look at the following code carefully, just look at it carefully when debugging.
// vue3-project/node_modules/launch-editor/index.js
function launchEditor(){
// 省略上部分...
if (
process.platform === 'linux' &&
fileName.startsWith('/mnt/') &&
/Microsoft/i.test(os.release())
) {
// Assume WSL / "Bash on Ubuntu on Windows" is being used, and
// that the file exists on the Windows file system.
// `os.release()` is "4.4.0-43-Microsoft" in the current release
// build of WSL, see: https://github.com/Microsoft/BashOnWindows/issues/423#issuecomment-221627364
// When a Windows editor is specified, interop functionality can
// handle the path translation, but only if a relative path is used.
fileName = path.relative('', fileName)
}
if (lineNumber) {
const extraArgs = getArgumentsForPosition(editor, fileName, lineNumber, columnNumber)
args.push.apply(args, extraArgs)
} else {
args.push(fileName)
}
if (_childProcess && isTerminalEditor(editor)) {
// There's an existing editor process already and it's attached
// to the terminal, so go kill it. Otherwise two separate editor
// instances attach to the stdin/stdout which gets confusing.
_childProcess.kill('SIGKILL')
}
if (process.platform === 'win32') {
// On Windows, launch the editor in a shell because spawn can only
// launch .exe files.
_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)
})
}
In this large segment, the main thing is following code , using the sub-process module. Simply put, the subprocess module has the ability to execute commands.
const childProcess = require('child_process')
if (process.platform === 'win32') {
// On Windows, launch the editor in a shell because spawn can only
// launch .exe files.
_childProcess = childProcess.spawn(
'cmd.exe',
['/C', editor].concat(args),
{ stdio: 'inherit' }
)
} else {
_childProcess = childProcess.spawn(editor, args, { stdio: 'inherit' })
}
At this point in the writing, it is basically close to the end. The principle is actually to use nodejs
in child_process
to execute a command code path/to/file
7. Summary
Here is a summary: First of all, at the beginning of the article, it proposes "the scenario where the source file corresponding to the page cannot be found in a short time", and gives a solution to the error situation that is easy to encounter.
Secondly, configure the debug learning environment along with the vue-devtools
especially the capital used in yyx990803 / Launch Editor- .
7.1 Briefly describe its principle in one sentence
Let's review the content of the principle at the beginning.
code path/to/file
Briefly explain the principle in one sentence: using nodejs
in child_process
, execute a code path/to/file
, and then the corresponding editor opens the corresponding file, and the corresponding editor executes ps x
in the process ( Window
uses Get-Process
) command. Of course, you can also specify the editor yourself.
What can be done in the end.
You can look at umijs/launch-editor and react-dev-utils/launchEditor.js . Their codes are almost similar.
You can also use Node.js
do some work such as improving development efficiency, and you can learn child_process
and other modules at the same time.
also don't imprison your own thinking, imprison the front end in the page, you should broaden your field of vision .
Node.js
for our front-end people to explore operating files, operating networks, etc.
If readers find something wrong or can be improved, or if there is no clear place, please comment and point out. In addition, I feel that it is well written, and it is a little helpful to you. You can like, comment, forward and share. It is also a kind of support for me. Thank you very much. If you can pay attention to my front-end public Vision" 160a0d7943df33, it would be better.
on
Hello, I’m , WeChat search Vision" 160a0d7943df8e Follow me, focus on front-end technology sharing, a vision is to help the front-end to broaden its horizons to the forefront of the public account within 5 years. Welcome to add me on WeChatruochuan12
for long-term exchange and learning.
There are mainly the following series of articles: learning source code overall architecture series , annual summary , JS basic series
Reference link
yyx990803/launch-editor
umijs/launch-editor
vuejs/vue-devtools
vue-devtools open-in-editor.md
"Open in editor" button doesn't work in Win 10 with VSCode if installation path contains spaces
react-dev-utils/launchEditor.js
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。