A demonstration of how to work with puppeteer using node2nix.
In package.json:
{
// ...
"bin": "index.js",
You should run node2nix --nodejs-10
, since node2nix will use a default of near-EOL NodeJS 8.x.
I typically use node2nix.nix
.
$ mv default.nix node2nix.nix
In node-packages.nix, add gitignoreSource
as an argument to the top level so we can filter gitignored sources.
{nodeEnv, fetchurl, fetchgit, globalBuildInputs ? [], gitignoreSource}:
Then go look for the src
attribute defined in the args
let-binding, and replace the definition.
args = {
name = "puppeteer-node2nix";
packageName = "puppeteer-node2nix";
version = "1.0.0";
- src = ./.;
+ src = pkgs.nix-gitignore.gitignoreSource [ ".git" ] ./.;
dependencies = [
Once these are done, you can add this argument to node2nix.nix
import ./node-packages.nix {
inherit (pkgs) fetchurl fetchgit;
+ inherit (pkgs.nix-gitignore) gitignoreSource;
inherit nodeEnv;
}
{ pkgs ? import <nixpkgs> {} }:
let
node2nix = import ./node2nix.nix { inherit pkgs; };
# note that this derivation does not work because the puppeteer
# package is not very nice. more details to follow.
package = node2nix.package;
in pkgs.stdenv.mkDerivation {
name = "puppeteer-node2nix-demo";
src = package;
installPhase = ''
mkdir -p $out/bin
ln -s $src/bin/puppeteer-node2nix $out/bin/puppeteer-node2nix
'';
}
Now you can try to build this package and observe puppeteer doing bad things: nix-build
(optionally with -j 10
to give it more jobs)
ERROR: Failed to download Chromium r674921! Set
"PUPPETEER_SKIP_CHROMIUM_DOWNLOAD" env variable to skip download.
- package = node2nix.package;
+ package = node2nix.package.override {
+ preInstallPhases = "skipChromiumDownload";
+ skipChromiumDownload = ''
+ export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
+ '';
+ };
Now you can build this and get a binary. But wait, if you run this, you will just get an error that Chormium is missing.
$ ./result/bin/puppeteer-node2nix
(node:1988) UnhandledPromiseRejectionWarning: Error: Chromium revision is not
downloaded. Run "npm install" or "yarn install"
Of course, you will soon find in the Puppeteer docs that you need to provide the PUPPETEER_EXECUTABLE_PATH
environment variable, with a path to the chromium
binary. That can be done easily using wrapProgram
.
in pkgs.stdenv.mkDerivation {
name = "puppeteer-node2nix-demo";
src = package;
+ buildInputs = [ pkgs.makeWrapper ];
installPhase = ''
mkdir -p $out/bin
ln -s $src/bin/puppeteer-node2nix $out/bin/puppeteer-node2nix
+
+ wrapProgram $out/bin/puppeteer-node2nix \
+ --set PUPPETEER_EXECUTABLE_PATH ${pkgs.chromium.outPath}/bin/chromium
'';
}
Now when we build the derivation, we can see the result that the original puppeteer-node2nix has now been wrapped with a script that will set the PUPPETEER_EXECUTABLE_PATH
environment variable:
$ ls -a result/bin/
. .. puppeteer-node2nix .puppeteer-node2nix-wrapped
Contents of puppeteer-node2nix
#! /nix/store/{someSha}-bash-4.4-p23/bin/bash -e
export PUPPETEER_EXECUTABLE_PATH='/nix/store/{someSha}-chromium-76.0.3809.87/bin/chromium'
exec -a "$0" "/nix/store/{someSha}-puppeteer-node2nix-demo/bin/.puppeteer-node2nix-wrapped" "${extraFlagsArray[@]}" "$@"
We can now run this as expected:
$ ./result/bin/puppeteer-node2nix
navigated to example.com
saved screenshot to example.png
I wrote a blog post about this here: https://github.com/justinwoo/my-blog-posts/blob/master/posts/2019-08-23-using-puppeteer-with-node2nix.md