Setup Macbook M1 for Web and React Native development

Published on Mar 14, 2021

12 min read

VSCODE

🕑 Updated on: March 14, 2022

cover_image

Note: Most of this article was updated in August 2021. The Macbook Pro M1 I was using crashed and stopped working without any reason on August 25, 2021. In just seven months of use.

It took time to get it repaired. That forced me to buy another laptop. While setting up the new laptop, I thought it is an excellent time to update this post.

I recently upgraded from Macbook Air 2017 to Macbook Pro with an M1 chip. My four-year-old Macbook Air was giving up. The performance to run heavy tasks like using the iOS simulator when developing and working on React Native apps was declining. I had long given up using the Android emulator and used an actual Android device for testing. December 2020 was the time I decided its time to upgrade.

I had a long internal discussion with myself for almost a month about whether I should upgrade to M1 or stick with Intel-based chips and spend them bucks. Don't get me wrong here, M1 is not cheap either as I did go for a RAM upgrade to max limits, which is currently 16GB in the base model.

After going through some online reviews and research, the kind of performance I was expecting has been worth it so far (it is fast, no doubt). I received it two weeks back when writing this post, and since then, I have installed all the necessary tools and utilities that help me work on Web development and React Native apps.

My local environment currently includes:

  • Homebrew (supports Apple Silicon machines since 2.6.0)
  • Git
  • Node.js
  • npm
  • Zsh
  • Oh My Zsh
  • iTerm
  • Xcode
  • yarn
  • VSCode
  • Rosetta 2

OS apps:

System Settings:

  • Disable Ask Siri
  • Disable Spotlight search except Applications, Calculator, Conversion, Definition, and System Preferences.
  • Trackpad:
    • Fix direction: Scroll & Zoom > Natural off
    • Right click: Point & Click > Secondary Click
    • Disable dictionary lookup: Point & Click > Look up & data detectors off
    • More gestures > Swipe between pages off & App Exposé off
  • Finder settings:
    • Preferences > Advanced > Show filename extensions
    • Enable show path bar: View > Show Path Bar
  • Dock:
    • Turn auto hiding on

Copy dotfiles.

System Preferences

🔗

Override default system preferences with from a terminal window:

# show hidden files
defaults write com.apple.finder AppleShowAllFiles YES
# show status bar
defaults write com.apple.finder ShowStatusBar -bool true
killall Finder;

iTerm

🔗

My favorite terminal app that I have been using for years is iTerm. I am currently using two versions of iTerm on my setup. One with Rosetta 2 enabled and the default one. This way, I can only use the Rosetta 2 emulator when required. There are no performance issues I have found with using iTerm with Rosetta 2 for ARM-based applications.

ss0

If you'd like a similar setup, go to the Applications folder in your Macbook and duplicate the iTerm application.

ss1

You can rename the duplicated iTerm app. I have renamed it to iTerm_rosetta to differentiate between the two. Right-click the duplicated app and click Get Info. In the General, check the box where it says Open using Rosetta.

ss2

Now, if you open the second terminal, it will be using Rosetta 2 emulator by default.

Other iTerm profile settings that I use:

Recently I started using Jetbrains Mono font.

ss6

For the overall looks and appearance, I use Dracula Pro Color Presets created by Zen Rocha.

ss7

And my last favorite thing is to split the working directory into two more different tabs using Command + D for horizontal panes.

Make sure to have the following setting configured from

General > Working Directory > select Advanced Configuration > click button Edit... > select Reuse previous session's directory under Working Directory for New Split Panes.

ss8

For terminal prompt, I use Spaceship ZSH.

Homebrew

🔗

On December 1, 2020, the Homebrew team announced on their website about the version release 2.6.0. The most significant changes among others they listed were the support for macOS Big Sur, using brew commands instead of brew cask and beginning to support macOS M1 and Apple Silicon or ARM-based chips.

Using the terminal, you can install the Homebrew by executing the default command:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

brew installs:

After installing Node.js

🔗

Node.js comes with default package manager npm. Set defaults for it:

npm set init.author.name "your name"
npm set init.author.email "you@example.com"
npm set init.author.url "example.com"

Xcode

🔗

After installing Git, for me, the next step is to install Xcode app from Apple's App Store.

Then, install "command line tools". It is required by many of the formulae in Homebrew.

xcode-select --install

After installing it, make sure to open it for the first time, from the menu bar, open Xcode > Preferences > Locations and make sure that Command Line Tools point towards the current Xcode app.

ss3

What is Karabiner-Elements?

🔗

When I bought Macbook Air M1, it had function keys (that got me excited), but I don't understand why Apple decided to replace function keys that would allow me to control Keyboard Brightness?! And moreover, replace it with "Do Not Disturb".

Why? That got me confused 🤷

I found this tool called karabiner Elements that can be installed as a brew formula:

brew install karabiner-elements

screenshot-of-function-keys-on-macbbok-air-m1-2020

Here are the key mappings I am using now:

key-mappings-with karabiner-elements

Git

🔗

I did install Git using brew command:

brew install git

To authenticate GitHub to be used from the terminal environment, I'd recommend you to check out the official document on creating and accessing personal tokens.

🔥 Tip: As of Git version 2.28 there is a new config option to set the default branch to main. Set it globally and forget about it.

git config --global init.defaultBranch main

ZSH and Oh My Zsh

🔗

ZSH is the default shell in macOS Big Sur. However, I like to use Oh My Zsh to manage the ZSH configuration, plugins, and a theme to prettify the terminal.

To install, run the command below:

sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

After installation, make sure that the file .zshrc is exporting the below path at the top:

# Path to your oh-my-zsh installation
export ZSH="/Users/<USERNAME>/.oh-my-zsh"

The first I like to do after setting up the bare minimum ZSH configuration is to install a plugin called zsh-syntax-highlighting. It provides syntax highlighting for the ZSH shell. Execute the series below commands in the terminal window:

# depending on the /plugins folder in your local setup
cd $HOME/.oh-my-zsh/plugins
# then clone the git repository
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git
echo "source ${(q-)PWD}/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" >> ${ZDOTDIR:-$HOME}/.zshrc

This is my final ZSH configuration in the file ~/.zshrc file:

# Path to your oh-my-zsh installation
export ZSH="/Users/amanhimself/.oh-my-zsh"
export PATH=/opt/homebrew/bin:$PATH
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
ZSH_THEME="spaceship"
# Uncomment the following line to disable bi-weekly auto-update checks.
DISABLE_AUTO_UPDATE="true"
plugins=(
git
node
vscode
zsh-syntax-highlighting
)
source $ZSH/oh-my-zsh.sh
source /Users/amanhimself/.oh-my-zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh

After installing the syntax highlight plugin, it starts to recognize the commands:

ss4

VSCode

🔗

VSCode and VS Code Insiders are currently supported on ARM chips (as of March 13, 2021). Download the installer for Insiders edition from here and for VSCode here.

ss5

I am still using the same VSCode configuration from my previous setup:

1{
2 // VSCODE EDITOR
3 "workbench.colorTheme": "fairyfloss",
4 "workbench.startupEditor": "welcomePage",
5 "workbench.iconTheme": "material-icon-theme",
6 "workbench.editor.tabSizing": "shrink",
7 "security.workspace.trust.untrustedFiles": "open",
8 "explorer.confirmDelete": false,
9 "explorer.confirmDragAndDrop": false,
10 "workbench.editor.enablePreview": false,
11 "window.restoreFullscreen": true,
12 "editor.tabSize": 2,
13 "editor.fontSize": 14,
14 "editor.minimap.enabled": false,
15 "editor.cursorBlinking": "phase",
16 "editor.fontLigatures": false,
17 "editor.wordWrap": "on",
18 "editor.cursorSmoothCaretAnimation": true,
19 "editor.tabCompletion": "on",
20 "editor.formatOnPaste": true,
21 "editor.formatOnSave": true,
22 "editor.semanticHighlighting.enabled": true,
23 "editor.guides.bracketPairs": true,
24 "breadcrumbs.enabled": false,
25 "explorer.openEditors.visible": 0,
26 "search.exclude": {
27 "**/node_modules": true,
28 "**/*.code-search": true,
29 "ios/": true,
30 "android/": true,
31 "dist/": true,
32 "yarn.lock": true,
33 "package-lock.json": true,
34 ".gitignore": true,
35 ".expo": true,
36 ".vscode": true
37 },
38 "extensions.autoUpdate": false,
39 // --------------------------------------
40 // EXPO TOOLS
41 "json.schemas": [
42 {
43 "name": "vscode-expo-manifest",
44 "url": "file:///Users/amanhimself/Library/Application%20Support/Code/User/globalStorage/bycedric.vscode-expo/manifest-42.0.0.json",
45 "fileMatch": ["app.json", "app.config.json"]
46 }
47 ],
48 // --------------------------------------
49 // CODE::STATS EXTENSION
50 "codestats.apikey": "api-key",
51 // --------------------------------------
52 // READ TIME EXTENSION
53 "readTime.enabled": true,
54 // --------------------------------------
55 // HIGHLIGHT MATCHING TAG EXTENSION
56 "highlight-matching-tag.styles": {
57 "opening": {
58 "name": {
59 // surround is border
60 "surround": "yellow"
61 }
62 }
63 },
64 // --------------------------------------
65 // INTEGRATED TERMINAL
66 // "terminal.integrated.defaultProfile.osx": "zsh",
67 "terminal.external.osxExec": "iTerm.app",
68 "terminal.integrated.fontSize": 12,
69 // --------------------------------------
70 // NPM
71 "npm-intellisense.importES6": true,
72 // --------------------------------------
73 // TS IMPORT SUGGESTION
74 "typescript.suggest.paths": false,
75 // --------------------------------------
76 // NATIVE BRACKER PAIR COLOR SETTINGS
77 "editor.bracketPairColorization.enabled": true,
78 "workbench.colorCustomizations": {
79 "editorBracketHighlight.foreground1": "#ffb86c",
80 "editorBracketHighlight.foreground2": "#8be9fd",
81 "editorBracketHighlight.foreground3": "#bd93f9",
82 "editorBracketHighlight.foreground4": "#50fa7b",
83 "editorBracketHighlight.foreground5": "#f1fa8c",
84 "editorBracketHighlight.foreground6": "#abb2c0",
85 "editorBracketHighlight.unexpectedBracket.foreground": "#ff5555"
86 },
87 // --------------------------------------
88 // PRETTIER ----------------------------------
89 "prettier.singleQuote": true,
90 "prettier.jsxSingleQuote": true,
91 "prettier.trailingComma": "none",
92 "prettier.arrowParens": "avoid",
93 "prettier.proseWrap": "preserve",
94 "prettier.quoteProps": "as-needed",
95 "prettier.jsxBracketSameLine": false,
96 "prettier.bracketSpacing": true,
97 "prettier.tabWidth": 2,
98 "editor.defaultFormatter": "esbenp.prettier-vscode",
99 // Markdown
100 "[markdown]": {
101 "editor.quickSuggestions": true
102 },
103 // JSON
104 "[json]": {
105 "editor.defaultFormatter": "esbenp.prettier-vscode"
106 },
107 // JavaScript
108 "[javascript]": {
109 "editor.defaultFormatter": "esbenp.prettier-vscode"
110 },
111 // JavaScript + React
112 "[javascriptreact]": {
113 "editor.defaultFormatter": "esbenp.prettier-vscode"
114 },
115 // TypeScript
116 "[typescript]": {
117 "editor.defaultFormatter": "esbenp.prettier-vscode"
118 },
119 // TypeScript + React
120 "[typescriptreact]": {
121 "editor.defaultFormatter": "esbenp.prettier-vscode"
122 },
123 // JSON with Comments
124 "[jsonc]": {
125 "editor.defaultFormatter": "esbenp.prettier-vscode"
126 },
127 // HTML
128 "[html]": {
129 "editor.defaultFormatter": "esbenp.prettier-vscode"
130 },
131 // ----------------------------------
132 // ESLINT
133 "eslint.validate": [
134 "javascript",
135 "javascriptreact",
136 "typescript",
137 "typescriptreact"
138 ],
139 // --------------------------------------
140 // LANGUAGES SPECIFIC
141 "javascript.updateImportsOnFileMove.enabled": "always",
142 "security.workspace.trust.banner": "never",
143 "emmet.includeLanguages": {
144 "typescript": "typescriptreact",
145 "javascript": "javascriptreact"
146 }
147}

Themes

🔗

I usually like to switch between a dark and a light theme.

Extensions

🔗

I use VSCode editor for both writing code and writing blog posts. Thus, the list of extensions below is the combination of extensions that fulfills both of my purposes.

Global NPM Packages I use

🔗

For React Native Development

🔗
  • install Node.js
  • install Watchman to watch changes in the filesystem using the command: brew install watchman
  • install following cocoapods: brew install cocoapods
  • According to a post by React Native guru Jamon Holmgren that all this time I've been using installing JDK wrong on my m1 machine 😱. To learn more how to install "the m1 way", go to his post and give it a read (and leave an appreciation clap 😄)
  • Versions later than Arctic Fox Canary now supports Apple's Silicon based machines for Android Studio. You can also check out the archive to see what beta/canary version supports Silicon machines
  • Then install Android SDK (I do not prefer AVD and use an actual device for testing)
  • scrcpy to display and control Android devices connect via USB on Mac

⚛️ For more instructions on how to set up a development environment for React Native, please follow the official documentation here.

Rosetta 2

🔗

Update: I am not using the Rosetta environment to install anything on the secondary machine since August 2021. That is the reason I've mentioned it at the end of the post.

Rosetta 2 is the lifeline that allows you to run apps designed for Intel-based chips that use x86 architecture on ARM-based chips (in this case M1). This solution is provided by Apple in the form of an emulator and doesn't come pre-installed. You have to install it manually. Fire up the Terminal application that comes pre-installed on the Big Sur and let your first command to execute be:

/usr/sbin/softwareupdate --install-rosetta --agree-to-license

If you decide not to put the flag --agree-to-license, you will be prompted by Apple's interactive install, and you will have to agree to their terms and license conditions to use it.

Conclusion

🔗

That’s the setup I now use for my JavaScript, Node.js, React and React Native. I think it's a good machine. Hopefully, M1 is just the beginning of a new era of powerful computers for daily work use 🤞

🤔 The only thing left for me is to find a way to transfer all laptop swag/stickers from my Macbook Air 2017 to Pro. I miss having them on this one.

isapplesiliconready.com is another helpful link I found to check what is compatible to work on Apple Silicon chips natively or using Rosetta or not optimized at all.

Share this article on Twitter


More Posts

Browse all posts

Join 1300+ devs & subscribe to my newsletter!

NEWSLETTER

🔗 Subscribe on Revue

AMAN MITTAL author

Software Developer and Technical Writer since 2017. Loves learning and writing about Node.js, React, React Native & Expo. Previously, a Developer Advocate at Draftbit.


Copyright ©  2019-2022 Aman Mittal · All Rights Reserved.