From d004c6b064dcb008df342835193abb85a0299503 Mon Sep 17 00:00:00 2001 From: Luke LaFountaine Date: Fri, 3 Dec 2021 16:52:18 -0500 Subject: [PATCH] [readme] clarify instructions for running Node on M1 Mac --- README.md | 105 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 59 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index be4561a..8346f0b 100644 --- a/README.md +++ b/README.md @@ -903,57 +903,70 @@ Homebrew causes insecure directories like `/usr/local/share/zsh/site-functions` **Macs with M1 chip** -_January 2021:_ there are no pre-compiled NodeJS binaries for versions prior to 15.x for Apple's new M1 chip (arm64 architecture). +Experimental support for the M1 architecture was added in node.js v15.3 and full support was added in v16.0. +Because of this, if you try to install older versions of node as usual, you will probably experience either compilation errors when installing node or out-of-memory errors while running your code. -Some issues you may encounter: +So, if you want to run a version prior to v16.0 on an M1 Mac, it may be best to compile node targeting the x86_64 Intel architecture so that Rosetta 2 can translate the x86_64 processor instructions to ARM-based Apple Silicon instructions. +Here's what you will need to do: -- using `nvm` to install, say, `v14.15.4`: - - the C code compiles successfully - - but crashes with an out of memory error when used - - increasing the memory available to node still produces the out of memory errors: - ```sh - $ NODE_OPTIONS="--max-old-space-size=4096" ./node_modules/.bin/your_node_package - ``` -- when using `nvm` to install some versions, the compilation fails -- after `nvm` successfully compiles some versions, `yarn` or `npm` may later fail to install packages with an `incorrect data check` error. +- Install Rosetta, if you haven't already done so -One solution to this issue is to change the architecture of your shell from arm64 to x86. + ```sh + $ softwareupdate --install-rosetta + ``` -Let's assume that: -- you already have versions `12.20.1` and `14.15.4` installed using `nvm` -- the current version in use is `14.15.4` -- you are using the `zsh` shell -- you have Rosetta 2 installed (macOS prompts you to install Rosetta 2 the first time you open a Intel-only non-command-line application, or you may install Rosetta 2 from the command line with `softwareupdate --install-rosetta`) + You might wonder, "how will my M1 Mac know to use Rosetta for a version of node compiled for an Intel chip?". + If an executable contains only Intel instructions, macOS will automatically use Rosetta to translate the instructions. -```sh -# Check what version you're running: -$ node --version -v14.15.4 -# Check architecture of the `node` binary: -$ node -p process.arch -arm64 -# This confirms that the arch is for the M1 chip, which is causing the problems. -# So we need to uninstall it. -# We can't uninstall the version we are currently using, so switch to another version: -$ nvm install v12.20.1 -# Now uninstall the version we want to replace: -$ nvm uninstall v14.15.4 -# Launch a new zsh process under the 64-bit X86 architecture: -$ arch -x86_64 zsh -# Install node using nvm. This should download the precompiled x64 binary: -$ nvm install v14.15.4 -# Now check that the architecture is correct: -$ node -p process.arch -x64 -# It is now safe to return to the arm64 zsh process: -$ exit -# We're back to a native shell: -$ arch -arm64 -# And the new version is now available to use: -$ nvm use v14.15.4 -Now using node v14.15.4 (npm v6.14.10) -``` +- Open a shell that's running using Rosetta + + ```sh + $ arch -x86_64 zsh + ``` + + Note: This same thing can also be accomplished by finding the Terminal or iTerm App in Finder, right clicking, selecting "Get Info", and then checking the box labeled "Open using Rosetta". + + Note: This terminal session is now running in `zsh`. + If `zsh` is not the shell you typically use, `nvm` may not be `source`'d automatically like it probably is for your usual shell through your dotfiles. + If that's the case, make sure to source `nvm`. + + ```sh + $ source "${NVM_DIR}/.nvm/nvm.sh" + ``` + +- Install whatever older version of node you are interested in. Let's use 12.22.1 as an example. + This will fetch the node source code and compile it, which will take several minutes. + + ```sh + $ nvm install v12.22.1 --shared-zlib + ``` + + Note: You're probably curious why `--shared-zlib` is included. + There's a bug in recent versions of Apple's system `clang` compiler. + If one of these broken versions is installed on your system, the above step will likely still succeed even if you didn't include the `--shared-zlib` flag. + However, later, when you attempt to `npm install` something using your old version of node.js, you will see `incorrect data check` errors. + If you want to avoid the possible hassle of dealing with this, include that flag. + For more details, see [this issue](https://github.com/nodejs/node/issues/39313) and [this comment](https://github.com/nodejs/node/issues/39313#issuecomment-902395576) + +- Exit back to your native shell. + + ```sh + $ exit + $ arch + arm64 + ``` + + Note: If you selected the box labeled "Open using Rosetta" rather than running the CLI command in the second step, you will see `i386` here. + Unless you have another reason to have that box selected, you can deselect it now. + +- Check to make sure the architecture is correct. `x64` is the abbreviation for x86_64, which is what you want to see. + + ```sh + $ node -p process.arch + x64 + ``` + +Now you should be able to use node as usual. ## Maintainers