Update template for Halogen 5 and Spago (#23)

Update template for Halogen 5 and Spago
master
Thomas Honeyman 2020-05-10 07:32:46 -07:00 committed by GitHub
parent 71dca24d9d
commit 93c34f2214
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 234 additions and 137 deletions

20
.gitignore vendored
View File

@ -1,8 +1,14 @@
/.*
!/.gitignore
!/.travis.yml
/bower_components/
/node_modules/
/output/
/dist/app.js
.*
!.gitignore
!.travis.yml
!.purs-repl
.spago
bower_components
node_modules
output
*.lock
package-lock.json
dist/app.js

1
.purs-repl Normal file
View File

@ -0,0 +1 @@
import Prelude

View File

@ -3,8 +3,7 @@ dist: trusty
sudo: required
node_js: stable
install:
- npm install -g bower
- npm install
- bower install
script:
- npm run build
- npm run test

View File

@ -1,72 +1,57 @@
# purescript-halogen-template
# Halogen Template
This is a template for starting a fresh project using the [purescript-halogen](https://github.com/slamdata/purescript-halogen) library for declarative user interfaces.
This is a template for starting a fresh project with the [Halogen](https://github.com/slamdata/purescript-halogen) library for writing declarative, type-safe user interfaces.
## Prerequisites
You can learn more about Halogen with these resources:
This guide assumes you already have Git and Node.js installed with `npm` somewhere on your path.
- The [Halogen documentation](https://github.com/purescript-halogen/purescript-halogen/tree/master/docs), which includes a quick start guide and a concepts reference.
- The [Learn Halogen](https://github.com/jordanmartinez/learn-halogen) learning repository.
- The [Real World Halogen](https://github.com/thomashoneyman/purescript-halogen-realworld) application and guide.
- The [API documentation](https://pursuit.purescript.org/packages/purescript-halogen) on Pursuit
In the PureScript ecosystem [Bower](http://bower.io/) is currently the most commonly used package manager and we'll be relying on it for this project, so if you don't already have it, you can install it like this:
``` shell
npm install --global bower
```
You can chat with other Halogen users on the [PureScript Discourse](https://discourse.purescript.org), or join the [Functional Programming Slack](https://functionalprogramming.slack.com) ([invite link](https://fpchat-invite.herokuapp.com/)) in the `#purescript` and `#purescript-beginners` channels.
## Getting started
First clone the repo and step into it:
**Prerequisites:** This template assumes you already have Git and Node.js installed with `npm` somewhere on your path.
``` shell
git clone https://github.com/slamdata/purescript-halogen-template.git my-halogen-project
cd my-halogen-project
First, clone the repository and step into it:
```sh
git clone https://github.com/purescript-halogen/purescript-halogen-template.git halogen-project
cd halogen-project
```
If you don't already have a global installation of the PureScript compiler and [Pulp](https://github.com/bodil/pulp) (or you want a local installation with the appropriate versions) you can run:
Then, install the PureScript compiler, the [Spago](https://github.com/purescript/spago) package manager and build tool, and [Webpack](https://github.com/webpack/webpack) bundler locally:
``` shell
```shell
npm install
```
Finally you'll need to install the PureScript library dependencies for this project with Bower:
``` shell
bower install
```
This will automatically trigger Spago to install the PureScript library dependencies for this project.
## Building
The project can now be built with:
You can now build the PureScript source code with:
``` shell
```sh
# An alias for `spago build`
npm run build
```
This will build the PureScript source code and produce a bundled JS file as `dist/app.js`.
You can produce a bundled JS file you can run in the browser with:
This is an alias for the Pulp command:
``` shell
pulp build --to dist/app.js
```sh
# An alias for `spago bundle-app --to dist/app.js`
npm run bundle
```
If you open `dist/index.html` you should now have a basic working Halogen app.
This deposits a bundled JS file named `app.js` in the `dist` directory. You can view your running Halogen app by opening the `dist/index.html` file.
You can also use the command:
Alternatively, if you use an editor that supports `purs ide` or if you are running [`pscid`](https://github.com/kRITZCREEK/pscid), then you can get near-instant builds of the app while you work:
``` shell
npm run watch
```sh
npm run bundle:watch
```
To start a process that will watch the source files and trigger a reload whenever they are modified. Alternatively...
## Fast watching with `purs ide`
If you're using an editor that supports `purs ide` or running [`pscid`](https://github.com/kRITZCREEK/pscid) there's an option for getting near-instant builds of the app while you work on it:
``` shell
npm run watch-fast
```
This will start a watch process that uses [Webpack](https://github.com/webpack/webpack) to rebundle the app whenever the _output_ files are changed. Since `purs ide` rebuilds modules on save, this means you can use this much faster bundle-only rebuild script.
:warning: `purs ide` only rebuilds one module at a time, so sometimes the bundle will end up in an inconsistent state, resulting in runtime errors. This occurs when a change is made in one module that breaks other modules that depend on it. The solution is to run a full build when a change like this is made, as the compiler will force you to resolve those errors.

View File

@ -1,17 +0,0 @@
{
"private": true,
"name": "purescript-halogen-template",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"output",
"dist"
],
"dependencies": {
"purescript-halogen": "^4.0.0",
"purescript-prelude": "^4.1.0",
"purescript-console": "^4.1.0",
"purescript-effect": "^2.0.0"
}
}

11
dist/index.html vendored
View File

@ -1,15 +1,8 @@
<!doctype html>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8"/>
<meta charset="utf-8" />
<title>My Halogen App</title>
<style>
body {
font-family: sans-serif;
max-width: 800px;
margin: auto;
}
</style>
</head>
<body>
<script src="app.js"></script>

View File

@ -1,15 +1,16 @@
{
"private": true,
"scripts": {
"build": "pulp build --to dist/app.js",
"watch": "pulp -w build --to dist/app.js",
"watch-fast": "webpack --mode=development --entry ./entry.js --output-path ./dist --output-filename app.js --progress --watch"
"test": "spago test",
"build": "spago build",
"bundle": "spago bundle-app --to dist/app.js",
"bundle:watch": "webpack --mode=development --entry ./entry.js --output-path ./dist --output-filename app.js --progress --watch"
},
"devDependencies": {
"pulp": "^12.3.0",
"purescript": "^0.12.0",
"purescript-psa": "^0.7.2",
"webpack": "^4.16.2",
"webpack-cli": "^3.1.0"
"purescript": "^0.13.6",
"purescript-psa": "^0.7.3",
"spago": "^0.15.2",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}

127
packages.dhall Normal file
View File

@ -0,0 +1,127 @@
{-
Welcome to your new Dhall package-set!
Below are instructions for how to edit this file for most use
cases, so that you don't need to know Dhall to use it.
## Warning: Don't Move This Top-Level Comment!
Due to how `dhall format` currently works, this comment's
instructions cannot appear near corresponding sections below
because `dhall format` will delete the comment. However,
it will not delete a top-level comment like this one.
## Use Cases
Most will want to do one or both of these options:
1. Override/Patch a package's dependency
2. Add a package not already in the default package set
This file will continue to work whether you use one or both options.
Instructions for each option are explained below.
### Overriding/Patching a package
Purpose:
- Change a package's dependency to a newer/older release than the
default package set's release
- Use your own modified version of some dependency that may
include new API, changed API, removed API by
using your custom git repo of the library rather than
the package set's repo
Syntax:
Replace the overrides' "{=}" (an empty record) with the following idea
The "//" or "⫽" means "merge these two records and
when they have the same value, use the one on the right:"
-------------------------------
let overrides =
{ packageName =
upstream.packageName // { updateEntity1 = "new value", updateEntity2 = "new value" }
, packageName =
upstream.packageName // { version = "v4.0.0" }
, packageName =
upstream.packageName // { repo = "https://www.example.com/path/to/new/repo.git" }
}
-------------------------------
Example:
-------------------------------
let overrides =
{ halogen =
upstream.halogen // { version = "master" }
, halogen-vdom =
upstream.halogen-vdom // { version = "v4.0.0" }
}
-------------------------------
### Additions
Purpose:
- Add packages that aren't already included in the default package set
Syntax:
Replace the additions' "{=}" (an empty record) with the following idea:
-------------------------------
let additions =
{ package-name =
{ dependencies =
[ "dependency1"
, "dependency2"
]
, repo =
"https://example.com/path/to/git/repo.git"
, version =
"tag ('v4.0.0') or branch ('master')"
}
, package-name =
{ dependencies =
[ "dependency1"
, "dependency2"
]
, repo =
"https://example.com/path/to/git/repo.git"
, version =
"tag ('v4.0.0') or branch ('master')"
}
, etc.
}
-------------------------------
Example:
-------------------------------
let additions =
{ benchotron =
{ dependencies =
[ "arrays"
, "exists"
, "profunctor"
, "strings"
, "quickcheck"
, "lcg"
, "transformers"
, "foldable-traversable"
, "exceptions"
, "node-fs"
, "node-buffer"
, "node-readline"
, "datetime"
, "now"
]
, repo =
"https://github.com/hdgarrood/purescript-benchotron.git"
, version =
"v7.0.0"
}
}
-------------------------------
-}
let upstream =
https://github.com/purescript/package-sets/releases/download/psc-0.13.6-20200507/packages.dhall sha256:9c1e8951e721b79de1de551f31ecb5a339e82bbd43300eb5ccfb1bf8cf7bbd62
let overrides = {=}
let additions = {=}
in upstream // overrides // additions

5
spago.dhall Normal file
View File

@ -0,0 +1,5 @@
{ name = "halogen-project"
, dependencies = [ "halogen", "psci-support" ]
, packages = ./packages.dhall
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
}

35
src/App/Button.purs Normal file
View File

@ -0,0 +1,35 @@
module App.Button where
import Prelude
import Data.Maybe (Maybe(..))
import Halogen as H
import Halogen.HTML as HH
import Halogen.HTML.Events as HE
type State = { count :: Int }
data Action = Increment
component :: forall q i o m. H.Component HH.HTML q i o m
component =
H.mkComponent
{ initialState: \_ -> { count: 0 }
, render
, eval: H.mkEval $ H.defaultEval { handleAction = handleAction }
}
render :: forall cs m. State -> H.ComponentHTML Action cs m
render state =
HH.div_
[ HH.p_
[ HH.text $ "You clicked " <> show state.count <> " times" ]
, HH.button
[ HE.onClick \_ -> Just Increment ]
[ HH.text "Click me" ]
]
handleAction :: forall cs o m. Action → H.HalogenM State Action cs o m Unit
handleAction = case _ of
Increment ->
H.modify_ \st -> st { count = st.count + 1 }

View File

@ -1,48 +0,0 @@
module Component where
import Prelude
import Data.Maybe (Maybe(..))
import Halogen as H
import Halogen.HTML as HH
import Halogen.HTML.Events as HE
data Query a = ToggleState a
type State = { on :: Boolean }
component :: forall m. H.Component HH.HTML Query Unit Void m
component =
H.component
{ initialState: const initialState
, render
, eval
, receiver: const Nothing
}
where
initialState :: State
initialState = { on: false }
render :: State -> H.ComponentHTML Query
render state =
HH.div_
[ HH.h1_
[ HH.text "Hello world!" ]
, HH.p_
[ HH.text "Why not toggle this button:" ]
, HH.button
[ HE.onClick (HE.input_ ToggleState) ]
[ HH.text
if not state.on
then "Don't push me"
else "I said don't push me!"
]
]
eval :: Query ~> H.ComponentDSL State Query Void m
eval = case _ of
ToggleState next -> do
_ <- H.modify (\state -> { on: not state.on })
pure next

View File

@ -1,13 +1,13 @@
module Main where
import Prelude
import App.Button as Button
import Effect (Effect)
import Halogen.Aff as HA
import Halogen.VDom.Driver (runUI)
import Component (component)
main :: Effect Unit
main = HA.runHalogenAff do
body <- HA.awaitBody
runUI component unit body
runUI Button.component unit body

10
test/Main.purs Normal file
View File

@ -0,0 +1,10 @@
module Test.Main where
import Prelude
import Effect (Effect)
import Effect.Class.Console (log)
main :: Effect Unit
main = do
log "You should add some tests."