Visual-Studio-Code
Visual Studio Code
Introduction
mike-works/vscode-fundamentals
Course outline and slides
View course outline here
View slides here
Editor Feature
Over time we’re seeing support for:
- Task running
- Workspace-specific settings
- A rich plugin ecosystem
- Things that analyze your code in the background
- A wide range of programming languages
Developer Focus
It’s built using web technology, for web developers, the Open Source way
👩💻 Delivering on features and an ecosystem that’s easy to jump into
🔌 Talks to web technologies more easily (i.e., Node talking to Node)
📖 Binaries are proprietary, but source code is open source
🗣 Close collaboration between the VS Code, Edge, Visual Studio and TypeScript teams’
Learning from past lessons
🚫 Don’t make ANOTHER heavy IDE
🔒 Don’t impose lots of opinions onto users
- ⌨️ Bring your keybindings with you
🤝 Favor open standards over proprietary formats
- i.e., .jsconfig, .editorconfig
Up and Running
Not just a new twist
🙌 Best cross-platform TypeScript development experience available
- Leverages TypeScript technology to give you insight into your regular JavaScript
👌 A great .NET development experience on OS X and Linux
- finally an OS maker that doesn’t lock us in
⏩ Doesn’t require a week of tweaking/config to get “right”
🚢 Shipping new features at an incredible rate!
Course Agenda
How this course is going to work
Agenda is as follows:
New code editing tricks (i.e. ⌘ + D along the way)
We’ll be working with JavaScript and TypeScript.
- It’s OK (maybe even better) if you don’t know TS yet
Using Visual Studio Code
- 📄 Awesome Documents
- ⏩ Emmet
- 🎛 Refactoring
- ✅ Type-Checking
- 🐞 Debugging
Setting Up
The best way to get to know this editor
Let’s use it to do some stuff!
Here’s the example we will be working with - a grocery app!

It’s a client/server app, built with bleeding edge versions of the following:
This is intended to show you the most modern web tools🔧 available. 95% of this can be done in older versions too!
Take a moment now to ensure you’re all set up. First, make sure you’re running a recent version of Node.js
1 | control + ` # 打开terminal的快捷键 |
1 | node --version # v8.0.0 or newer |
And we need a library called sqlite3 for our database. You can check your version by running
1 | # If you don't have it yet |
And it’s helpful to have a package manager called yarn
1 | # If you don't have it yet |
1 | git clone https://github.com/mike-north/vscode-fundamentals vscode |
NEXT: 📄 Awesome Documents
Documents
Markdown
Images
Normal markdown images
1 |  |

The HTML <img> tag can be used as well. Many attributes will be respected in most markdown renderers (including GitHub)
1 | <img src="../../public/vscode.png" height=50 align=right vspace=20/> |
👉 Keep in mind that, in this case, GitHub wraps each image in
1 | <p> |
Alignment
The align attribute can be used on a variety of HTML tags
1 | <p align=right>right ➡</p> |
right ➡
⬅ center ➡
⬅ left
If you wrap multiple inline elements in a <p> tag, it’s possible to do some interesting things with vertical align attribute values
1 | <p> |
Lists
Unordered Lists
These can be nested to create a multi-level outline
Markdown Lint的规则是使用加号
1 | * one |
- one
- two
- three
- four
- three
Ordered Lists
These cannot be nested in most markdown rendering engines
1 | 1. first |
- first
- second
- third
but, if you use HTML, you can fix this, and customize the list “type”
1 | <ol type='A' > |
- first
- second
- third
- fourth
- fifth
Description Lists (<dl>)
1 | <dl> |
- Images
- .jpg, .gif, .png
- Styles
- .css
- Scripts
- .js
- Documents
- .html
Details/Summary
1 | <details> |
Click me for something absolutely amazing
1 | let Hello : string = 'World'; |
1 | | Item | Price | Qty | |
| Item | Price | Qty |
|---|---|---|
| 🍇 Grapes | $2.99 | 3 |
| 🍐 Pears | $4.15 | 1 |
| 🍋 Lemons | $0.99 | 2 |
Thanks to folks who posted tips I didn’t know about!
NEXT: ⏩ Emmet
Most useful Detail, second Align
Emmet & Html
Emmet Autocompletions
- Speed up repetitive task with
TAB - Plugins for most editors
- Built into VS Code
- Works in JSX
Emmet: HTML Elements
- Think of as CSS selectors for DOM generation
- Cursor usually ends up placed just where you want it to be next
div
1 | <div></div> |
.foo
1 | <div class="foo"></div> |
span.foo#bar
1 | <span class="foo" id="bar"></span> |
img
1 | <img src="" alt=""> |
Nesting & Sibling
- Just like in CSS, we can use…
| Selector | Description |
|---|---|
> |
Direct decendant selector |
+ |
Sibling selector |
ul>li.special-item
1 | <ul> |
.navbar+.content+.footer
1 | <div class="navbar"></div> |
We can also use the “climb up” operator: ^
div+div>p>span+em^bq
1 | <div></div> |
Personally, I prefer using parentheses (grouping) rather than climb-up
div+div>(p>(span+em))+bq
1 | <div></div> |
There’s a feature called “multiplication” that’s useful for lists
ul.col>li.col-item*5
1 | <ul class="col"> |
And you can even add text to the body of elements, with a placeholder for number in the list
ul.col>li.col-item*5{Item $}
1 | <ul class="col"> |
Emmet: CSS
Emmet: Styles
- Lots of different combinations(too many to remember)
- Value aliases are pretty easy to get used to
| Alias | Value |
|---|---|
p |
Percent |
e |
em |
r |
rem |
px |
px |
- Rule of thumb: first letter of each word for a property
| Emmet | Evaluates to |
|---|---|
w100p! |
width: 100% !important |
lh1.5r |
line-height: 1.5rem |
op50p |
opacity: 50% |
Tips for Productive Emmet use
- No newlines or spaces
- You can create custom shortcuts(more on this later)
- Aim for several small expansions, rather than one huge expansion
- Start basic, and add new shortcuts over time
Challenge 1: Rapid Expansion
We want to add a new tile to the right of each category row, as shown here 👉
You’ll need to edit therenderfunction in client/routes/home/category-row/index.tsx
There’s a per-category image you can use, which take the form/images/fallback-<lowercase-category-name>.png. (i.e., http://localhost:3000/images/fallback-frozen.png)
Use Emmet autocompletions to build the appropriate HTML structure
1
2
3
4
5
6
7
8 <li class="GroceryItem mui-panel">
<h4 class="item-name">
Click Here for More
</h4>
<span class="click-for-more">
<img class='item-image' src=? />
</span>
</li>⚠️ React likes
className=notclass=
⚠️ You interpolate dynamic and static values in JSX like this
1 <img alt={`my value is ${3 + 4}`} />
Code Navigation & Refactoring
Go To
- …file
- …definition
- …type definition
- …symbol
- …in file
- …in workspace
- …line(by number)
Selection
- Select All Cmd + A
- Select Next Occurrence Cmd + D
- Select All Occurrence Shift + Cmd + L
Multi-Cursor & Line Manipulation
Multi-Cursor
- Add cursor @ position Opt + Click
- Box select Opt + Shift + Click
- Undo last cursor Cmd + U
Line Manipulation
- Move line up Opt + ⬆️
- Move line down Opt + ⬇️
- Copy line below Opt + Shift + ⬇️
Peek Editing
- Opens up a split in editor
- Peek at type definition
- Find all References
Renaming
- Level 1: Find/Replace Cmd + F
- Level 2: Cmd + D for selection
- Level 3: “Extract into function” and F2 for rename in ALL FILES
Challenge 2: Refactoring
- Make the following changes to /client/data/listener-support.js
registerandunregistershould be changed toregisterListenerandunregisterListener, respectivelyfireshould be passed an object of the structure{data: object[]}
- Ensure that all places in the code that call
fireare updated to use this new structure- No code that registers listeners should need to be altered as a consequence of this change
Type Checking
Introducing Type Checking
Typechecking
- VS Code has TypeScript at its core
- TypeChecking is becoming increasingly popular
- React’s proptypes(runtime)
- Facebook’s flow(static)
- Microsoft’s TypeScript(static)
- TypeScript is a typed superset of JavaScript
- It heavily relies on type inference - the automatic deduction of the data type of an expression
- As of TypeScript 2.3 VS Code can apply type checking to your JavaScript
- Type information can be added via JSDoc comments!
Benefits of Types
Why would I want to use Types?
- Catch more bugs at compile time
- Better developer experience
- Your code becomes a better expression of your intent
1
function add(x, y) { /* ? */}
- Avoid common situations where your code is de-optimized
Categories of Type Systems
Nominal Typing
Decisions about whether types are equivalent are made based on their name - Nominal type system
Structural Typing
Decisions about whether types are equivalent are made based on their structure - Structural type system
1 | interface CartItem { |
Because VS Code uses TypeScript to check our code, it uses structural type system.
Type Checking in VS Code
Activating Type-Checking in VS Code.
- If your project already is set up for typescript, just add
"checkJs": trueto yourtsconfig.json. - Otherwise, add a comment at the top of your JS file.
1 | // @ts-check |
Annotating Types
Annotating Types with JSDoc.
- Types can be added with comments
1 | /** @type {number} */ |
- Constructors are regarded as types too!
- Remember, this is still structural!
- TypeScript has a bulit-in type definition for the DOM API and other common JavaScript constructs
1 | /** @type {Element} */ |
- Sometimes we work with code that provides us with a less specific type than what we want
1 | getFruit('orange'); // 🍊 |
- In the above class, perhaps we really wanted the JavaScript representation of an
<input>, not just a generic element!
1 | /** @type {HTMLInputElement} */ |
- This would be no problem if
Element‘s structure was a superset ofHTMLInputElement‘s, but it’s the other way around. - The TypeScript compiler has found that
Elementis lacking the accept property. - We can perform an explicit type conversion(type casting)
1 | /** @type {HTMLInputElement} */ |
- At this point, the explicit declaration dosen’t add any value
1 | let x = /** @type {HTMLInputElement} */( |
Functions
- Function is a first-class value type
- We can also define a structure of a function(arguments)
1 | /** @type {function(MouseEvent)[]} */ |
- Arrow functions => can also be used to define argument types
1 | /** @type {(request: Request) => Response} */ |
- Note that we have defined a return type as well here. We could also have used @return
- Keep in mind: this is just static analysis. Function passed as arguments aren’t checked for argument type alignment.
Generics
- Operate across many types
- Still maintain compile-time type safety
1 | /** |
- Promises and other things that wrap other values (which have their own types) are defined using this concept of generics
- Be careful when mixing types with JSX!
1 | /** @type {PromiseLike<string>} */ |
Custom Types
Defining our own named types.
- We can use @typedef to create a new named type of our own
- Two ways to do this:
1 | /** |
Challenge 3: Data Layer Types
- Updata the TypeScript compiler configuration to
"CheckJs": true- Type-check JavaScript files"noImplicitAny": true- Complain about “implicit any” types (i.e, require us to provide an explicit type in spots where the compiler can’t infer well enough)
- Add a variety of JSDoc type annotations to
- client/data/listener-support.js
- Type of
this._listenersbe an array of function with argument types specified.
- Type of
- client/data/grocery-item-store.js
- client/data/cart-store.js
- You may find that you need to define a “grocery item” type in this file and
grocery-item-store.js. - This is fine
- You may find that you need to define a “grocery item” type in this file and
- client/data/order-store.js
- client/data/listener-support.js
- Eliminate all complaints about implicit use of the
anytype (visible in theproblemandterminal) - HINT:
ArrayLike<T>covers things likeReadonlyArray<T>andArray<T>
Debugging
Debugging Node
Node has no GUI, so the built-in debugging experience is 🤢 (vomoticon). Let’s take a look!
1 | npm run debug |
Thankfully, in May 2016 we got a new flag that basically
- 🛑 Suspends global node.js execution on the first line of code
- 🔗 Gives us a URL to open w/ chrome
1 | npm run debug:attach |
Under the hood, this runs node --inspect --inspect-brk.
Debugging Node with Editors
This still involves a ton of context switching
- 👎 Yes, this is a bad thing
- 🔫 Multitasking stockholm syndrome(斯德哥尔摩综合症)
- 🐟 Seems like we’ve been floundering around for a decade trying to get this right



👆 This one was/is actually really cool, but…
- insanely hard to set up
- and brittle
- and looks like it works
- but it doesn’t really
There are some community sourced Atom plugins

But these plugins are complex and need a HUGE amount of effort to get right
- sourcemaps
- advanced debugging features
- asynchrony
- multiple threads
- multiple debugging sessions
Debugging Node with VS Code
- Start node with same
--inspectand--inspect-brkflags
1 | npm run debug:inspect |
- Open the Debugger side panel
- Create a new “lanuch configuration” that looks like this
1 | { |
- Now press the Lunch▶️ button to attach the Node runtime
- Inspector vs Legacy Protocol
- Launch vs. Attach
- Conditional breakpoints
- Restart Frame
- Column Breakpoints
- Skipping Code
Debugging Chrome with VS Code
We just need another launch configuration
1 | { |
We can lunch this at the same time as our node debugger
Challenge 4: Muliti-Process Debugging
- Try adding something to the cart. There’s a suble bug involving a misunderstanding between client & server about > data format
- Set a breakpoint in /client/data/cart-store.js’s
_saveCart()function right before thePUTrequest is sent - Set a breakpoint in /server/routes/cart.js’s
.put("/items")handler, keeping an eye on the body of the HTTP request as it lands - Use the above guidelines to create “attach” launch configurations for both Chrome and Node
- Find and fix the problem
- You should be able to (almost) step from one breakpoint to the other
Workspace Customization
Benefits of Customization
Why Customize Your Workspace
- Developer spend LOTS of time in their editor
- What can confirguration do for you?
- Speed up your workflow
- Make it easier to read code
- Spot errors
- Reduce fatigue
Levels of customization
- 🖥Workspace
./.vscode/setting.json - 👨💻User
- Windows
%APPDATA%\Code\User\settings.json - Mac
$HOME/Library/Application Support/Code/User/settings.json - Linux
$HOME/.config/Code/User/settings.json
- Windows
- Defualt that ship with the editor
- Edit via Cmd + ,
VS Code Themes
- 🎨 Color Theme
- 🗂 File Icon Theme
- ⚙️ Customize colors in settings
- 📚 IntelliSense, a variety of code editing features will be helpful here
1 | "workbench.colorCustomizations": { |
- 🖍 Syntax Highlighting Customizations
1 | "editor.tokenColorCustomizations": { |
Custom Fonts
Setting up a custom font
- Lots of FREE fonts specifically for developers
1 | "editor.fontFamily": "Fira Code", |
Key Bindings
- Start with a Keymap from your preferred editor
- Search for extensions:
@recommended:keymaps
- Search for extensions:
- Basic customizations in Keyboard Shortcuts Cmd + K Cmd + S
- Advanced customizations in
keybindings.json
1 | { |
Key Bindings for Visual Studio Code
Code Snippets
- Prefix is what you’ll type (and then hit Tab)
${1:300}means "first placeholder, which initially has a value of 300"- When filling out this templete, repeated use of a given placeholder is updated
1 | "For Loop": { |
Challenge 5: VS Code Tune-Up
- Make some UI color customizations, that apply across all projects
- Panel: background
#033 - Badge: foreground
#000, background:#ff0 - Status bar while debugging: foreground #000, background:
#ff0 - Currently active editor tab: foreground:
#0ff - Peek editor: background:
#311
- Panel: background
- Design your own syntax highlighting scheme. If you need ideas: https://coolors.co/browser/best/1
- Disable the minimap
- Disable the indent guides
- Create a code snippet for a placeholder image in HTML files
- Shortcut: ph
- Result:
<img src='http://placecorgi.com/{x}/{y}' />where x and y default to 300
Tasks
Introducting Custom VS Code Tasks
About Tasks
- Run build steps, linting, testing, deploying scripts from within VS Code
- Anything in a
gruntfile,Gulpfile, package.json ("scripts") should be auto-detected - Where's the best place for these files to live?
- Main stuff:
package.jsonor Scripty - VS Code specifics layered on top
- Main stuff:
- Ability to parse "problems" from output, linking to file and line number
Custom tasks in tasks.json
- Define one or more things in the
tasksarray - Basic Example of a
"type": "shell"task
1 | { |
Tasks: Shell Command Arguments
- It's best to use the
"args"property to ensure arguments are properly quoted
1 | { |
- We can add a working directory option as well, to ensure this runs at our project root folder
1 | { |
Tasks: Capturing output into "problems"
- If the output of this command printed indications of problems in our code (at a particular file/line), we can use Command + Click 🖲 on a file path to open that file
1 | "taskName": "echo", |
- But what about pointing out problems by line/column?
This task would output something like this:
1 | client/index.tsx,LINE:8,this line stinks |
What we need is a regular expression with capture groups
Cheat sheet
1 | [0-9] any number |
EXAMPLE: If our string is LINE:31, and we use a regex:
1 | LINE:([0-9]+) |
- Group 0: “LINE:31”
- Group 1: “31”
Let’s figure out the appropriate regex
Once we have this, we can use it within our task to detect the files, line #s, and specific details for any problems that are found:
1 | { |
And we should see the following in our “problems” tab

and clicking on the problem should take us right to the appropriate line in the appropriate file

Challenge 6: TSLint Problems
- Think of it as “ESLint for TypeScript”
- You can run this via
./node_modules/.bin/tslint --project <root of your workspace> click for sample output
ERROR: /Users/northm/Development/workshops/vscode/client/components/app-header/index.tsx[22, 7]: Identifier 'cartIcon' is never reassigned; use 'const' instead of 'let'.
- Create a custom task to run TSLint
- Define a regex-based Problem Matcher to capture output, so that any issues found are shown in the “problems” panel
- Fix all the bugs it points out (Cycle through problems with F8)
Launch Confirguration
Launch Setting
launch.jsonis where launch confirgurations live- We’ve dealt with launch & config in Debugging exercise 4
- Let’s break it down:
1 | { |
"type:" ?
- You will only need to worry about two types for now:
"node"for Node"chrome"for Chrome
- Others can be added via extensions
runtimeExecutable:" ?
- This is the runtime that you pass your code into, to run
- Default value: determined by
"typeof debugger - Practical Example:
./node_modules/.bin/ts-node - Usually accompanied by something like
"program": "./index.js"
"restart:" ? (Node)
- Automatically re-executes the command when Node terminates
- In an
"attach"mode, VS Code will start listening for connections again and preserve your breakpoints
Console Options
- Where does the output go?
1 | "console": "integratedTerminal" // "Terminal" |
- How the console at the bottom of the editor is dealt with:
1 | "internalConsoleOptions": "neverOpen" // Don't open |
Arguments & Environment
"args": []property takes care of quoting properly"env": {}object is for environment variables"cwd": "./"for working directory- Default to
"${workspaceRoot}"
- Default to
Variables
${workspaceRoot}- the path of the folder opened in VS Code${workspaceRootFolderName}- the name of the folder opened in VS Code without any slashes (/)${file}- the current opened file${relativeFile}- the current opened file relative to workspaceRoot${fileBasename}- the current opened file’s basename${fileBasenameNoExtension}- the current opened file’s basename with no file extension${fileDirname}- the current opened file’s dirname${fileExtname}- the current opened file’s extension${cwd}- the task runner’s current working directory on startup${lineNumber}- the current selected line number in the active file
Challenge 7: Analyze & Monitor
Build two new launch configurations
- Show a bundle analysis visualization
- Ultimately this command needs to be run
ANALYIZE=true node ./server/index.js(ANALYZE is an environment variable) - We don’t want to have to “attach” to this. Just let it run
- Ultimately this command needs to be run
- Launch our server, but use
nodemonto have it restart as we save files- You’ll need to install the
nodemonnpm package globally (npm install -g nodemon) - Ultimately the command you’ll need to run is something like
nodemon ./server/index.js - Running this should result in the debug console opening, but only when we “launch”, not on every restart
- We shouldn’t have to “attach” to this. It should be a one-click launch
- You’ll need to install the