Node.js: Difference between revisions
→Packaging: example on how to package a npm package with flakes |
m →Setup: suggest search.nixos.org instead of cli nix search |
||
| (5 intermediate revisions by 4 users not shown) | |||
| Line 5: | Line 5: | ||
== Setup == | == Setup == | ||
Adapt or add following line to your system configuration:<syntaxhighlight lang="nix> | Adapt or add following line to your system configuration:<syntaxhighlight lang="nix> | ||
environment.systemPackages = with pkgs; [ nodejs ]; | |||
</syntaxhighlight> | </syntaxhighlight> | ||
See | See [https://search.nixos.org/packages?&query=nodejs NixOS Package Search] for additional versions like <code>nodejs_20</code>, etc. | ||
== Development environment == | |||
Also see [[Development environment with nix-shell]] on this wiki. | |||
=== Nixpkgs example === | |||
{{file|shell.nix|nix|3= | |||
{ pkgs ? import <nixpkgs> {} }: | |||
pkgs.mkShell { | |||
nativeBuildInputs = with pkgs.buildPackages; [ | |||
nodejs_22 | |||
yarn | |||
]; | |||
} | |||
}} | |||
=== Corepack example === | |||
To use specific/pinned versions of your runtime & package manager, a combination of corepack & steam-run can be used | |||
{{file|shell.nix|nix|3= | |||
{ pkgs ? import <nixpkgs> {} }: | |||
pkgs.mkShell { | |||
buildInputs = with pkgs; [ | |||
corepack | |||
steam-run-free | |||
]; | |||
shellHook = '' | |||
alias deno="steam-run pnpm deno" | |||
''; | |||
} | |||
}} | |||
{{file|package.json|json|3= | |||
{ | |||
"packageManager": "pnpm@11.4.0", | |||
"devEngines": { | |||
"runtime": { | |||
"name": "deno", | |||
"version": "^2.7.14", | |||
"onFail": "download" | |||
} | |||
} | |||
} | |||
}} | |||
== Packaging == | == Packaging == | ||
| Line 72: | Line 115: | ||
<syntaxhighlight lang="console"> | <syntaxhighlight lang="console"> | ||
$ nix-shell -p yarn yarn2nix | $ nix-shell -p yarn yarn2nix | ||
$ yarn install | $ yarn install # creates yarn.lock | ||
# creates yarn.lock | |||
$ yarn2nix > yarn.nix | $ yarn2nix > yarn.nix | ||
$ vim package.json | $ vim package.json # add: "bin": "app.js", | ||
# add: | |||
$ cat > default.nix <<EOF | $ cat > default.nix <<EOF | ||
with (import <nixpkgs> {}); | with (import <nixpkgs> {}); | ||
| Line 125: | Line 166: | ||
This is done through configuring npm and amending your <tt>PATH</tt>.<ref>[https://logs.nix.samueldr.com/nixos/2018-07-09#1358500 joepie91 on #nixos, 2018-07-09]</ref> | This is done through configuring npm and amending your <tt>PATH</tt>.<ref>[https://logs.nix.samueldr.com/nixos/2018-07-09#1358500 joepie91 on #nixos, 2018-07-09]</ref> | ||
< | <syntaxhighlight lang="console"> | ||
$ npm set prefix ~/.npm-global | |||
</ | </syntaxhighlight> | ||
Then, amend your <tt>PATH</tt> so it looks into <tt>$HOME/.npm-global</tt>. | Then, amend your <tt>PATH</tt> so it looks into <tt>$HOME/.npm-global</tt>. | ||
| Line 135: | Line 176: | ||
This is a bit harder to implement, but creates a bit more strictness in your environment; it will be impossible accidentally make use of what would have been a globally installed package. The idea is to install it to either a temporary transitory folder or to the project folder, then run the locally installed instance of the package, the binaries are found under <tt>node_packages/.bin/</tt>.<ref>[https://logs.nix.samueldr.com/nixos/2018-07-17#1386090; samueldr on #nixos, 2018-07-17]</ref> | This is a bit harder to implement, but creates a bit more strictness in your environment; it will be impossible accidentally make use of what would have been a globally installed package. The idea is to install it to either a temporary transitory folder or to the project folder, then run the locally installed instance of the package, the binaries are found under <tt>node_packages/.bin/</tt>.<ref>[https://logs.nix.samueldr.com/nixos/2018-07-17#1386090; samueldr on #nixos, 2018-07-17]</ref> | ||
< | <syntaxhighlight lang="console"> | ||
$ npm install uglify-es | |||
[ ... ] | [ ... ] | ||
$ ls -l node_modules/.bin/ | |||
total 0 | total 0 | ||
lrwxrwxrwx 1 user users 25 Jul 17 15:34 uglifyjs -> ../uglify-es/bin/uglifyjs | lrwxrwxrwx 1 user users 25 Jul 17 15:34 uglifyjs -> ../uglify-es/bin/uglifyjs | ||
$ node_modules/.bin/uglifyjs --help | |||
Usage: uglifyjs [options] [files...] | Usage: uglifyjs [options] [files...] | ||
</ | </syntaxhighlight> | ||
===== direnv ===== | ===== direnv ===== | ||
| Line 159: | Line 200: | ||
==== Using <code>npx</code> ==== | ==== Using <code>npx</code> ==== | ||
< | <syntaxhighlight lang="console"> | ||
$ nix-shell -p nodejs-8_x | |||
$ npx create-react-app --help | |||
npx: installed 67 in 1.671s | npx: installed 67 in 1.671s | ||
Usage: create-react-app <project-directory> [options] | Usage: create-react-app <project-directory> [options] | ||
[...] | [...] | ||
</ | </syntaxhighlight> | ||
==== Using <code>npx</code> with binaries ==== | ==== Using <code>npx</code> with binaries ==== | ||
| Line 175: | Line 216: | ||
For example, <code>npx cypress open</code> might give an error like: | For example, <code>npx cypress open</code> might give an error like: | ||
< | <syntaxhighlight lang="console"> | ||
$ npx cypress open | $ npx cypress open | ||
| Line 185: | Line 226: | ||
---------- | ---------- | ||
spawn /home/rkb/.cache/Cypress/4.10.0/Cypress/Cypress ENOENT | spawn /home/rkb/.cache/Cypress/4.10.0/Cypress/Cypress ENOENT | ||
</ | </syntaxhighlight> | ||
One quick workaround for this is [[Steam#FHS environment only| to use <code>steam-run</code>]] to provide a placeholder FHS environment that *should* work; e.g. for the Cypress example above: | One quick workaround for this is [[Steam#FHS environment only| to use <code>steam-run</code>]] to provide a placeholder FHS environment that *should* work; e.g. for the Cypress example above: | ||
< | <syntaxhighlight lang="console"> | ||
$ nix-env -iA nixos.steam-run | $ nix-env -iA nixos.steam-run | ||
| Line 195: | Line 236: | ||
-- Cypress opens successfully! | -- Cypress opens successfully! | ||
</ | </syntaxhighlight> | ||
(Inspired by [https://discourse.nixos.org/t/how-to-make-nixos-so-easy-that-people-can-be-productive-up-front-without-having-to-first-learn-the-nix-language/5625 this discussion on discourse.nixos.org]) | (Inspired by [https://discourse.nixos.org/t/how-to-make-nixos-so-easy-that-people-can-be-productive-up-front-without-having-to-first-learn-the-nix-language/5625 this discussion on discourse.nixos.org]) | ||
| Line 201: | Line 242: | ||
'''Google-fonts fetch failure with NextJS''' | '''Google-fonts fetch failure with NextJS''' | ||
Nextjs is a popular React framework and comes with built-in support with support for Google fonts. If a NPM project uses it, <syntaxhighlight lang=" | Nextjs is a popular React framework and comes with built-in support with support for Google fonts. If a NPM project uses it, <syntaxhighlight lang="console"> | ||
npm run build # which calls "next build" | $ npm run build # which calls "next build" | ||
</syntaxhighlight>will try to fetch and optimize the Google fonts during a nix build run, which will fail in Nix's isolated sandbox without internet:<syntaxhighlight lang="shell"> | </syntaxhighlight>will try to fetch and optimize the Google fonts during a nix build run, which will fail in Nix's isolated sandbox without internet:<syntaxhighlight lang="shell"> | ||
... | ... | ||
| Line 236: | Line 277: | ||
ERROR: `npm build` failed | ERROR: `npm build` failed | ||
</syntaxhighlight>You have to patch the Javascript code <syntaxhighlight lang="javascript"> | </syntaxhighlight>You have to patch the Javascript code <syntaxhighlight lang="javascript"> | ||
// In layout.tsx file replace | |||
// | |||
// import {Inter} from "next/font/google"; // or any other Google font like Inter | |||
// const inter = Inter({ subsets: ["latin"] }); | |||
// | |||
// with ("src:" must be relative to the src/app/layout.tsx file): | |||
import localFont from "next/font/local"; | import localFont from "next/font/local"; | ||
const inter = localFont({ src: './Inter.ttf' }); | const inter = localFont({ src: './Inter.ttf' }); | ||
| Line 259: | Line 300: | ||
... | ... | ||
} | } | ||
</syntaxhighlight>You can take a look at what fonts are available in the Nix <code>google-fonts</code> package by calling:<syntaxhighlight lang=" | </syntaxhighlight>You can take a look at what fonts are available in the Nix <code>google-fonts</code> package by calling:<syntaxhighlight lang="console"> | ||
ls -ahl $(nix build --no-link --print-out-paths nixpkgs#google-fonts)/share/fonts/truetype/ | $ ls -ahl $(nix build --no-link --print-out-paths nixpkgs#google-fonts)/share/fonts/truetype/ | ||
</syntaxhighlight>Take a look at https://github.com/NixOS/nixpkgs/blob/ | </syntaxhighlight>Take a look at [https://github.com/NixOS/nixpkgs/blob/8358fd43a66594d8b3445d87006185fa76d4be6e/pkgs/by-name/ho/homepage-dashboard/package.nix homepage-dashboard package in nixpkgs] for further workarounds for Nextjs in Nix. | ||
== Tips and tricks == | == Tips and tricks == | ||
=== Example nix flake shell for Node.js development === | === Example nix flake shell for Node.js development === | ||
[[Flake]] example: | [[Flake]] example: (Note: the `${&lt;nixpkgs&gt;}` needs to be replaced by `${<nixpkgs>}` | ||
{{file|flake.nix|nix| | {{file|flake.nix|nix| | ||
<nowiki> | <nowiki> | ||
| Line 312: | Line 353: | ||
<syntaxhighlight lang="nix> | <syntaxhighlight lang="nix> | ||
final: prev: { | final: prev: { | ||
nodejs = prev.nodejs-16_x; | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
< | <syntaxhighlight lang="console"> | ||
$ pnpm node --version | $ pnpm node --version | ||
v16.17.1 | v16.17.1 | ||
</ | </syntaxhighlight> | ||
=== Override NodeJS package === | === Override NodeJS package === | ||