diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d9755b39..3bcc24328 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ Bugfixes - Fix `spago run` and `spago test` to accept command line arguments correctly, by writing a JS file to run (#865, #866) - Remove support for node versions older than 12.0.0 as they do not work with es modules (#866) +Other improvements: +- Update README.md with documentation for v0.15 + ## [0.20.7] - 2022-02-12 Bugfixes diff --git a/README.md b/README.md index 2c0f2613e..5bb132179 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Other installation methods available: Let's set up a new project! -```bash +```console $ mkdir purescript-unicorns $ cd purescript-unicorns $ spago init @@ -75,7 +75,7 @@ Let's take a look at the two [Dhall][dhall] configuration files that `spago` req To build your project, run: -```bash +```console $ spago build ``` @@ -85,21 +85,21 @@ of JavaScript has been generated from your new `Main.purs` file. You can already see your project running, by doing -```bash +```console $ spago run ``` ..which is basically equivalent to the following command: -```bash -$ node -e "require('./output/Main/index').main()" +```console +$ node -e "import('./output/Main/index').then(m => m.main())" ``` ..which imports the JS file you just looked at, and runs the `main` with Node. You can also bundle the project in a single file with an entry point, so it can be run directly (useful for CLI apps): -```bash +```console $ spago bundle-app $ node . ``` @@ -247,14 +247,14 @@ you'll have to carefully: For an overview of the available commands, run: -```bash +```console $ spago --help ``` You will see several subcommands (e.g. `build`, `test`); you can ask for help about them by invoking the command with `--help`, e.g.: -```bash +```console $ spago build --help ``` @@ -265,7 +265,7 @@ This will give a detailed view of the command, and list any command-specific Since `spago init` does not necessarily use the latest package set. Fortunately, you can specify which package set to use via the `--tag` argument. See the [`purescript/package-sets` repo's releases](https://github.com/purescript/package-sets/releases) for tags you can use: -```bash +```console $ spago init --tag "psc-0.13.8-20200822" ``` @@ -274,7 +274,7 @@ $ spago init --tag "psc-0.13.8-20200822" You can add dependencies that are available in your package set by running: -```bash +```console # E.g. installing Halogen $ spago install halogen @@ -285,7 +285,7 @@ $ spago install foreign simple-json ### Download my dependencies locally -```bash +```console $ spago install ``` @@ -300,7 +300,7 @@ to be installed will run this for you. We can build the project and its dependencies by running: -```bash +```console $ spago build ``` @@ -315,7 +315,7 @@ are CommonJS modules, and you can just `require()` them e.g. on Node. It's also possible to include custom source paths when building (the ones declared in your `sources` config are always included): -```bash +```console $ spago build --path 'another_source/**/*.purs' ``` @@ -323,14 +323,14 @@ $ spago build --path 'another_source/**/*.purs' **Note**: the wrapper on the compiler is so thin that you can pass options to `purs`. E.g. if you wish to output your files in some other place than `output/`, you can run -```bash +```console $ spago build --purs-args "-o myOutput/" ``` If you wish to automatically have your project rebuilt when making changes to source files you can use the `--watch` flag: -```bash +```console $ spago build --watch # or, to clear the screen on rebuild: @@ -343,25 +343,25 @@ $ spago build --watch --allow-ignored To run a command before a build you can use the `--before` flag, eg to post a notification that a build has started: -```bash +```console $ spago build --watch --before "notify-send 'Building'" ``` To run a command after the build, use `--then` for successful builds, or `--else` for unsuccessful builds: -```bash +```console $ spago build --watch --then "notify-send 'Built successfully'" --else "notify-send 'Build failed'" ``` Multiple commands are possible - they will be run in the order specified: -```bash +```console $ spago build --watch --before clear --before "notify-send 'Building'" ``` If you want to run the program (akin to `pulp run`), just use `run`: -```bash +```console # The main module defaults to "Main" $ spago run @@ -384,7 +384,7 @@ $ spago run --node-args "arg1 arg2" You can also test your project with `spago`: -```bash +```console # Test.Main is the default here, but you can override it as usual $ spago test --main Test.Main Build succeeded. @@ -395,13 +395,10 @@ Tests succeeded. ### Run a repl -As with the `build` and `test` commands, you can add custom source paths -to load, and pass options to the underlying `purs repl` via `--purs-args`. - -E.g. the following opens a repl on `localhost:3200`: +You can start a repl with the following command: -```bash -$ spago repl --purs-args "--port 3200" +```console +$ spago repl ``` @@ -414,7 +411,7 @@ By default, the following dependencies are installed: `effect`, `console`, `prel You can run a script via the following, optionally specifying a package set to use, and additional dependencies to pull from there: -```bash +```console $ spago script --tag psc-13.8 -d node-fs path/to/script.purs ``` @@ -427,13 +424,13 @@ It is sometimes useful to know which packages are contained in our package set You can get a complete list of the packages your `packages.dhall` imports (together with their versions and URLs) by running: -```bash +```console $ spago ls packages ``` By using the `ls deps` command instead you can restrict the list to direct or transitive dependencies: -```bash +```console # Direct dependencies, i.e. only the ones listed in spago.dhall $ spago ls deps @@ -490,7 +487,7 @@ in upstream Note that if we do `spago ls packages`, we'll see that it is now included as a local package: -```bash +```console $ spago ls packages ... signal v10.1.0 Remote "https://github.com/bodil/purescript-signal.git" @@ -581,7 +578,7 @@ E.g. if you patched the `foreign` package, and added it as a local package to yo you can check that you didn't break its dependents (also called "reverse dependencies") by running: -```bash +```console $ spago verify foreign ``` @@ -606,7 +603,7 @@ Spago can update the package set to the latest release or to a specific release Running it would look something like this: -```bash +```console $ spago upgrade-set [info] Updating package-set tag to "psc-0.13.8-20200822" Fetching the new one and generating hashes.. (this might take some time) @@ -617,7 +614,7 @@ Fetching the new one and generating hashes.. (this might take some time) If the package set exists, running `upgrade-set` would look something like this: -```bash +```console $ spago upgrade-set --tag "psc-0.13.8-20200822" [info] Updating package-set tag to "psc-0.13.8-20200822" Fetching the new one and generating hashes.. (this might take some time) @@ -626,7 +623,7 @@ Fetching the new one and generating hashes.. (this might take some time) If the package set does not exist, your `packages.dhall` file will not be touched and you will see a warning: -```bash +```console spago upgrade-set --tag "whoops-i-made-a-big-typo" [info] Updating package-set tag to "whoops-i-made-a-big-typo" Fetching the new one and generating hashes.. (this might take some time) @@ -756,7 +753,7 @@ in conf // { ``` And then you can run tests like this: -```bash +```console $ spago -x test.dhall test ``` @@ -769,7 +766,28 @@ there are basically two ways to do that: This will produce a single, executable, dead-code-eliminated file: -```bash +**>= v0.15.0** + +Since v0.15.0 spago uses `esbuild` as the underlying default bundler. See the [`esbuild` getting started](https://esbuild.github.io/getting-started/#install-esbuild) for installation instructions. +```console +# You can specify the main module and the target file, or these defaults will be used. This will bundle for the browser by default. +$ spago bundle-app --main Main --to index.js +Bundle succeeded and output file to index.js + +# If you want to minify the build, use +$ spago bundle-app --main Main --to index.js --minify + +# Or if you want to bundle for node +$ spago bundle-app --main Main --to index.js --platform node +Bundle succeeded and output file to index.js + + +# We can then run it with node: +$ node . +``` + +**<= v0.14.0** +```console # You can specify the main module and the target file, or these defaults will be used $ spago bundle-app --main Main --to index.js Bundle succeeded and output file to index.js @@ -780,10 +798,24 @@ $ node . #### 2. `spago bundle-module` -If you wish to produce a single, dead-code-eliminated JS module that you can `require` from +If you wish to produce a single, dead-code-eliminated JS module that you can `import` from JavaScript: -```bash +**>= v0.15.0** + +```console +# You can specify the main module and the target file, or these defaults will be used +$ spago bundle-module --main Main --to index.js +Bundling first... +Bundle succeeded and output file to index.js +Make module succeeded and output file to index.js + +$ node -e "import('./index.js').then(m => console.log(m.main))" +[Function] +``` + +**<= v0.14.0** +```console # You can specify the main module and the target file, or these defaults will be used $ spago bundle-module --main Main --to index.js Bundling first... @@ -821,6 +853,44 @@ To start a project using Spago and Parcel together, here's the commands and file It is recommended to read any environment variables in the JavaScript file and pass them as arguments to `main`. Here is an example JavaScript file: + **>= v0.15.0** + ```js + import * as Main from './output/Main/index'; + + function main () { + /* + Here we could add variables such as + + var baseUrl = process.env.BASE_URL; + + Parcel will replace `process.env.BASE_URL` + with the string contents of the BASE_URL environment + variable at bundle/build time. + A .env file can also be used to override shell variables + for more information, see https://en.parceljs.org/env.html + + These variables can be supplied to the Main.main function. + However, you will need to change the type to accept variables, by default it is an Effect. + You will probably want to make it a function from String -> Effect () + */ + + Main.main(); + } + + // HMR setup. For more info see: https://parceljs.org/hmr.html + if (module.hot) { + module.hot.accept(function () { + console.log('Reloaded, running main again'); + main(); + }); + } + + console.log('Starting app'); + + main(); + ``` + + **<= v0.14.0** ```js var Main = require('./output/Main'); @@ -918,8 +988,15 @@ To start a project using Spago and Parcel together, here's the commands and file 1. Follow [Spago's "Super quick tutorial"](#super-quick-tutorial) 2. Initialise a JavaScript/npm project with `npm init` 3. Add Webpack and purescript-psa as development-time dependencies: `npm install --save-dev webpack webpack-cli webpack-dev-server purescript-psa` -4. Install the PureScript loader and HTML plugin for WebPack `npm install --save-dev purs-loader html-webpack-plugin`. +4. **>= v0.15.0** + + Install the HTML plugin for WebPack `npm install --save-dev html-webpack-plugin`. + + **<= v0.14.0** + + Install the PureScript loader and HTML plugin for WebPack `npm install --save-dev purs-loader html-webpack-plugin`. Note that you may require additional loaders for css/scss, image files, etc. Please refer to the [Webpack documentation](https://webpack.js.org/) for more information. + 5. Create an HTML file that will serve as the entry point for your application. Typically this is `index.html`. In your HTML file, be sure to pull in the `bundle.js` file, which will be Webpack's output. Here is an example HTML file: @@ -939,6 +1016,80 @@ To start a project using Spago and Parcel together, here's the commands and file 6. Create a `webpack.config.js` file in the root of your project. Here is an example webpack configuration: + **>= v0.15.0** + ```js + import path from 'path' + import HtmlWebpackPlugin from 'html-webpack-plugin' + import webpack from 'webpack' + import { dirname } from 'path'; + import { fileURLToPath } from 'url'; + + const __dirname = dirname(fileURLToPath(import.meta.url)); + const isWebpackDevServer = process.argv.some(a => path.basename(a) === 'webpack-dev-server') + const isWatch = process.argv.some(a => a === '--watch') + + const plugins = + isWebpackDevServer || !isWatch ? [] : [ + function () { + this.plugin('done', function (stats) { + process.stderr.write(stats.toString('errors-only')) + }) + } + ] + + + export default { + devtool: 'eval-source-map', + mode: 'development', + devServer: { + port: 4008, + static: { + directory: path.resolve(__dirname,'dist'), + }, + }, + + entry: './index.js', + + output: { + path: path.resolve(__dirname,'dist'), + filename: 'bundle.js' + }, + + module: { + rules: [ + { + test: /\.(png|jpg|gif)$/i, + use: [ + { + loader: 'url-loader', + options: { + limit: 8192, + }, + }, + ], + }, + ] + }, + + resolve: { + modules: ['node_modules'], + extensions: ['.js'] + }, + + plugins: [ + new webpack.LoaderOptionsPlugin({ + debug: true + }), + new HtmlWebpackPlugin({ + title: 'purescript-webpack-example', + template: 'index.html', + inject: false // See stackoverflow.com/a/38292765/3067181 + }) + ].concat(plugins) + } + ``` + + **<= v0.14.0** ```js 'use strict'; @@ -1032,6 +1183,15 @@ To start a project using Spago and Parcel together, here's the commands and file Please refer to the Webpack documentation on environment variable replacement during bundling. Here is an example `index.js` file: + **>= v0.15.0** + ```js + import { main } from '../output/Main/index' + + main() + console.log('app starting'); + ``` + + **<= v0.14.0** ```js 'use strict'; @@ -1048,6 +1208,16 @@ To start a project using Spago and Parcel together, here's the commands and file Also, make sure you are calling `main` properly if you are passing arguments (due to PureScript specifics of [modelling effectful computations](https://stackoverflow.com/a/55750945/3067181)): + **>= v0.15.0** + + ```js + + var arg1 = 'arg1'; + main(arg1)(); + + ``` + + **<= v0.14.0** ```js var arg1 = 'arg1'; @@ -1057,11 +1227,22 @@ To start a project using Spago and Parcel together, here's the commands and file 8. Add the following development script to `package.json`: + **>= v0.15.0** ```js ... "scripts": { ..., - "webpack:server": "webpack-dev-server --progress --inline --hot" + "webpack:server": "spago build -w & webpack-dev-server --progress --hot" + }, + ... + ``` + + **<= v0.14.0** + ```js + ... + "scripts": { + ..., + "webpack:server": "webpack-dev-server --progress --hot" }, ... ``` @@ -1088,7 +1269,31 @@ To start a project using Spago and Parcel together, here's the commands and file It is recommended to read any environment variables in the JavaScript file and pass them as arguments to `main`. Here is an example JavaScript file: + + **>= v0.15.0** + ```js + import * as Main from './output/Main'; + function main () { + /* + Here we could add variables such as + + var baseUrl = process.env.BASE_URL; + + Node will replace `process.env.BASE_URL` + with the string contents of the BASE_URL environment + variable at bundle/build time. + + These variables can be supplied to the Main.main function, + however, you will need to change the type to accept variables, by default it is an Effect. + You will probably want to make it a function from String -> Effect () + */ + + Main.main(); + } + ``` + + **<= v0.14.0** ```js 'use strict' @@ -1154,7 +1359,7 @@ it is recommended that you pre-compile your PureScript project before distributi To build documentation for your project and its dependencies (i.e. a "project-local [Pursuit][pursuit]"), you can use the `docs` command: -```bash +```console $ spago docs ``` @@ -1162,13 +1367,13 @@ This will generate all the documentation in the `./generated-docs` folder of you You might then want to open the `index.html` file in there. If you wish for the documentation to be opened in browser when generated, you can pass an `open` flag: -```bash +```console $ spago docs --open ``` To build the documentation as Markdown instead of HTML, or to generate tags for your project, you can pass a `format` flag: -```bash +```console $ spago docs --format ctags ``` @@ -1181,6 +1386,7 @@ Quoting from [this tweet](https://twitter.com/jusrin00/status/109207140735638732 something like `parcel`, to avoid mangling/destroying the sourcemaps 3. now you can see your breakpoints in action +**Note**: In >= v0.15.0 this needs to be `import * as someModule from './output/Whatever/index.js'` ### Use alternate backends to compile to Go, C++, Kotlin, etc @@ -1478,7 +1684,7 @@ To get a ballpark value for the `j` flag you can take the result of the `ulimit If you encounter any issues with the hashes for the package-set (e.g. the hash is not deemed correct by `spago`), then you can have the hashes recomputed by running the `freeze` command: -```bash +```console $ spago freeze ```