This guide offers a simple set of steps to get up and running with PureScript with the goal of building projects in a way that is reproducible and consistent regardless of the underlying development environment.
Rather than provide a ready-made starter app, the objective is to provide some contextual understanding of how to achieve a streamlined and reliable workflow for your PureScript projects.
The following steps will take you from a blank slate to a functioning "Hello World" SPA.
You'll want to clone and work inside of this repository when following the instructions below.
Nix is a powerful package manager for Linux and other Unix systems that makes package management reliable and reproducible.
By using Nix as the starting point for your project, you'll be creating a sandbox for any underlying node/npm dependencies and avoiding polluting the global environment of your system.
$ curl https://nixos.org/nix/install | sh
A Nix channel represents a static set of packages that will not change
in a way that breaks compatibility or affects dependencies. You can find
out what the latest stable channel is
on the Nix website. As of today,
the latest stable channel is 18.09
.
$ nix-channel --add https://nixos.org/channels/nixos-18.09 nixpkgs
A Nix derivation (build action) is a declarative set of build instructions
which define how to build a specific set of dependent packages in a
predictable way. The default.nix
file included in this repository
defines a derivation to import a recent (stable) version of nodejs
and psc-package
.
Invoking nix-shell
command will build the dependencies of the derivation
specified, and it will start an interactive environment in which all
environment variables defined by the derivation are set accordingly.
The default.nix
derivation also contains a PATH
setting to allow
the invocation of locally installed NPM packages from the command-line.
$ nix-shell default.nix
# npm is now available
$ npm --version
6.2.0
Now that you are inside the Nix environment with NPM installed, you
can move on to installing PureScript and Pulp.
Pulp is essentially
a frontend for the PureScript compiler, purs
.
$ npm install purescript pulp
...
+ [email protected]
+ [email protected]
added 133 packages in 11.614s
You can opt to use bower
or
psc-package
for managing dependencies
within your project. Using psc-package
will allow you to work from
a curated set of packages for which the dependencies have been resolved.
For Haskell users, psc-package
is more less analogous to stack
in
the Haskell ecosystem.
If desired, you can fork the psc-package
set yourself to guarantee
that no underlying packages versions will change behind the scenes, and
you can also use your forked repository to add custom packages you'd like
to make available in your project. Doing so is just a matter of modifying
psc-package.json
.
# Example of a custom package set.
{
"name": "my-project",
"set": "psc-0.10.2",
"source": "https://github.com/joeuser/package-sets.git",
"depends": [
"prelude"
]
}
The psc-package
binary is provided by the default.nix
derivation that
we shelled into earlier. You can use psc-package
to initialize your
project and install whatever packages you need. Any packages installed
via NPM or psc-package
will be local to this repository, so you can
always get back to a blank slate just by removing the cloned repository
and starting over from scratch.
# initialize psc-package project
$ psc-package init
# pin to a known package set
$ sed -i 's/"set":.*/"set": "psc-0.12.3",/' psc-package.json
# add repl support
$ psc-package install psci-support
# add list support
$ psc-package install lists
# add foldable support
$ psc-package install foldable-traversable
# install deps required for building a web app
$ psc-package install effect
$ psc-package install hedwig
Now you can test your setup via the repl.
$ psc-package repl
PSCi, version 0.12.1
Type :? for help
> import Prelude
> import Data.List
> import Data.Foldable
> foldr (+) 0 (1..10)
55
It's worth noting that you can side-step needing both NPM and psc-package and offload all of your package management needs to Nix; however, this increases the complexity on the Nix side of the equation and falls outside of the scope of this document.
That said, here are some resources if you want to explore doing everything in Nix.
The final step is to add libraries to facilitate developing an SPA in PureScript. For this example, we'll use Hedwig, a declarative PureScript library for building web applications, as Hedwig follows TEA, a familiar design pattern for developing SPA; however, you should explore the list of available libraries and choose whatever best fits your needs.
# install the required npm packages from package.json
$ npm install
# watch for changes and re-compile as needed
$ npm start
From here, you can open index.html
, and you should see Hedwig's
example counter application running in your browser. Pulp will recompile
your project whenever you make changes to your code, so you get hot
reloading for free!
The package.json
file includes uglify
and a script hook to minify
the Javascript emitted from purs
and get it ready for production.
The pulp
invocation inside of package.json
includes the --optimise
flag which performs dead code elimination to minimize the footprint of
the Javascript that's generated.
$ npm run dist
> [email protected] dist /private/tmp/howto
> mkdir -p dist/js && uglifyjs js/*.js -m -o dist/js/index.js && cp index.html dist/
$ tree dist
dist
├── index.html
└── js
└── index.js
1 directory, 2 files
$ ls -lh dist/js/index.js | awk '{print $4}'
44K
The contents of the dist
directory are ready to
deploy to your favorite CDN.
Put simply, PureScript sucks the least out of all the FP frontend languages available. Take advantage of some of the excellent resources available to further your understanding of the language, and go build something!
Helpful resources: