Skip to content

Commit 1566f93

Browse files
authored
Merge pull request #5 from faucet-pipeline/docs
Docs
2 parents 3777779 + 34418e6 commit 1566f93

File tree

1 file changed

+361
-0
lines changed

1 file changed

+361
-0
lines changed

README.md

Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
# faucet-pipeline
2+
3+
**tl;dr: faucet-pipeline is a framework-independent, pluggable asset pipeline
4+
that takes the pain out of preprocessing JavaScript, CSS and associated files
5+
(e.g. images or fonts). It simplifies the process of converting modern
6+
JavaScript (ES6) to support older browsers (ES5), or Sass to CSS - eliminating
7+
typical low-level configuration nightmares.**
8+
9+
* [Getting Started](#getting-started)
10+
* [Description](#description)
11+
* [Manifest Files & Integration with
12+
Frameworks](#manifest-files--integration-with-frameworks)
13+
* [CLI](#cli)
14+
* [Config File](#config-file)
15+
* [Sponsors & Users](#sponsors--users)
16+
* [Background](#background)
17+
* [Troubleshooting / Frequently Asked Questions
18+
(FAQ)](#troubleshooting--frequently-asked-questions-faq)
19+
* [License](#license)
20+
21+
22+
## Getting Started
23+
24+
* install:
25+
26+
```
27+
$ npm install faucet-pipeline-js faucet-pipeline-sass
28+
```
29+
30+
* configure ([learn more about this file](#config-file)):
31+
32+
```javascript
33+
let js = {
34+
manifest: {
35+
file: "dist/manifest-js.json",
36+
baseURI: "/assets"
37+
},
38+
bundles: [{
39+
entryPoint: "index.js",
40+
target: "dist/bundle.js",
41+
transpiler: {
42+
features: ["es2015"]
43+
}
44+
}]
45+
};
46+
47+
let sass = {
48+
manifest: {
49+
file: "dist/manifest-css.json",
50+
baseURI: "/assets"
51+
},
52+
bundles: [{
53+
entryPoint: "index.scss",
54+
target: "dist/bundle.css"
55+
}]
56+
};
57+
58+
59+
module.exports = { js, sass };
60+
```
61+
62+
* compile ([learn more about the CLI options](#cli)):
63+
64+
```
65+
$ node_modules/.bin/faucet
66+
```
67+
68+
## Description
69+
70+
The faucet-pipeline is a command line application written in Node.js that takes
71+
the development version of your assets to deliverable versions. By assets, we
72+
mean files like JavaScript, CSS, image and font files. faucet-pipeline relies on
73+
established tooling rather than reinventing the wheel, but provides a greatly
74+
simplified, unified interface with reasonable defaults.
75+
76+
Why do the development versions of these files differ from their deliverable
77+
version? For one, it is not uncommon to have your JavaScript distributed over a
78+
lot of different files, but wanting to deliver a single (or a handful) of
79+
JavaScript files to your client. You might also want to reduce the size of these
80+
files by removing comments from them. Or you might even want to translate them
81+
from one language to another one (like Sass to CSS).
82+
83+
In addition, it is a good practice to fingerprint the assets you want to
84+
deliver. That means that their file names change when the content changes. This
85+
allows you to set the cache expiration date onto something far in the future
86+
because when the file changes, this cache will not be used. Read more about it
87+
in the Manifest Files section.
88+
89+
In development, you also might want to run this entire process every time a file
90+
is changed that would change the result.
91+
92+
This is what faucet-pipeline does. And it does this by offering you different
93+
modules (for example one for JavaScript and one for Sass) that you can choose
94+
from depending on your project. It also allows you to do some configuration like
95+
“Where are the files that need to be compiled?” or “Where should they be put?”,
96+
but not much more. This reduces the amount of configuration you need to do
97+
and allows us to switch out parts when newer, better parts become available
98+
without you needing to change anything but the version number.
99+
100+
## Manifest Files & Integration with Frameworks
101+
102+
Each of the pipelines generates a manifest file. The manifest file provides
103+
information about where to find the files. This is necessary as they are
104+
fingerprinted. The file is in JSON and is an object.
105+
106+
The manifest looks like this:
107+
108+
```json
109+
{
110+
"output/example.css": "/assets/output/example.css"
111+
}
112+
```
113+
114+
The key is the `target` of the according bundle. The value is dependent on your
115+
manifest configuration:
116+
117+
1. If your `baseURI` is a String, it will be `${baseURI}${target}`
118+
2. If your `baseURI` is a function, it will be the return value of your
119+
function (see [Config](#config-file) for details).
120+
121+
If you choose to use fingerprinting, then the right side will also be
122+
fingerprinted. The idea is that in your Web app you provide a helper that is
123+
provided with the key and will put out the value. You can then use it in your
124+
template engine so that you don't need to hardcode the fingerprinted version.
125+
126+
A helper like this is currently available for the following
127+
frameworks/languages:
128+
129+
* [Ruby on Rails](https://github.com/fejo-dk/rails_external_asset_pipeline):
130+
Full integration into helpers like `stylesheet_link_tag`.
131+
132+
If you've written another adapter, please open a PR to add it to the list.
133+
134+
## CLI
135+
136+
If you call the `faucet` command without any arguments, it will default to
137+
building your project according to the configuration in the file `faucet.js` in
138+
the current directory. You have the following options:
139+
140+
* `-c $FILENAME` or `--config=$FILENAME`: Use the file `$FILENAME` as the
141+
configuration file.
142+
* `-w` or `--watch`: Build once, afterward watch for file changes and rebuild
143+
when a file that is used for one of your bundles changes.
144+
* `--no-fingerprint`: Suppress fingerprinting in the file names.
145+
* `--compact`: Use a compact output format for all pipelines that support it
146+
(currently faucet-pipeline-sass and faucet-pipeline-js). Comments will be
147+
stripped from the output etc. This doesn't do minification (variable name
148+
mangling etc.) due to our `view-source:` conviction.
149+
150+
We recommend that you use a combination of `--watch` and `--fingerprint` for
151+
development (fingerprinting is not very useful in development and it also
152+
reduces clutter on your disk) and `--compact` for production.
153+
154+
## Config File
155+
156+
The config file for faucet is a JavaScript file. In this file, you should export
157+
an object that contains the configuration. For each pipeline you want to use,
158+
you need to export an object with the according configuration. In addition, you
159+
can do some general configuration of the file watcher. So it might look
160+
something like this:
161+
162+
```js
163+
module.exports = {
164+
js: {
165+
// configuration for faucet-pipeline-js
166+
},
167+
sass: {
168+
// configuration for faucet-pipeline-sass
169+
},
170+
watchDirs: {
171+
// configuration for file watching
172+
}
173+
}
174+
```
175+
176+
Each of the configurations is optional. If you don't want to use Sass, you could
177+
only export a `js` option. The pipelines will only be required if you provided
178+
an option for them. Therefore you would only need to install
179+
`faucet-pipeline-js` in that case.
180+
181+
Each of the configurations (`js`, `sass`) requires a `manifest` configuration.
182+
If you don't need a manifest file, set `manifest` to `false`. Otherwise, you
183+
provide an object with two keys: `file` and `baseURI`. `file` is the path where
184+
your manifest file should be written (relative to the config file). `baseURI`
185+
can be either:
186+
187+
1. If your `baseURI` is a String, the manifest values will be generated
188+
like this: `${baseURI}${target}`
189+
2. If your `baseURI` is a function, it will be the return value of your
190+
function. The function will be provided with two arguments: `target` and
191+
`path.basename(target)`.
192+
193+
For example, it could look like this:
194+
195+
```js
196+
module.exports = {
197+
sass: {
198+
manifest: {
199+
file: "css.json",
200+
baseURI: "/assets"
201+
},
202+
// ...
203+
}
204+
}
205+
```
206+
207+
### Configuration for `faucet-pipeline-js`
208+
209+
The configuration has to include a `bundles` key with an array. Each entry of
210+
the array if an object with two keys: `entryPoint` is the file that should be
211+
compiled, and `target` is the file that should be created (the path is, of
212+
course, modified a little when you use fingerprinting). It also has a third,
213+
optional key `transpiler`. If you provide it, the pipeline will transpile ES201*
214+
to ES3. You need to provide an object with a `transpiler` key that has an array
215+
with features that you want to transpile as an argument.
216+
217+
If you for example want to transpile from ES2015 to ES3, your configuration
218+
could look like this:
219+
220+
```js
221+
module.exports = {
222+
js: {
223+
manifest: {
224+
file: "dist/manifest.json",
225+
baseURI: "/assets"
226+
},
227+
bundles: [{
228+
entryPoint: "index.js",
229+
target: "dist/bundle.js",
230+
transpiler: {
231+
features: ["es2015"]
232+
}
233+
}]
234+
};
235+
};
236+
```
237+
238+
### Configuration for `faucet-pipeline-sass`
239+
240+
The configuration has to include a `bundles` key with an array. Each entry of
241+
the array if an object with two keys: `entryPoint` is the file that should be
242+
compiled, and `target` is the file that should be created (the path is, of
243+
course, modified a little when you use fingerprinting).
244+
245+
There are also two optional configurations:
246+
247+
* `assets`: If you want to use images or fonts in your CSS files that are also
248+
fingerprinted, you can provide an array of paths to manifest files here. You
249+
can then use the `asset-url` Sass function in your code. You provide the "left
250+
side" of your manifest file as an argument, and it will be replaced with
251+
`url(...)` with the dots being the "right side" of your manifest.
252+
* `prefixes`: A configuration for the
253+
[autoprefixer](https://github.com/postcss/autoprefixer).
254+
255+
The resulting configuration could look something like this:
256+
257+
```js
258+
module.exports = {
259+
sass: {
260+
manifest: {
261+
file: "./css.json",
262+
baseURI: "/assets"
263+
},
264+
assets: [
265+
"./images.json"
266+
],
267+
prefixes: {
268+
browsers: [
269+
"last 2 versions"
270+
]
271+
},
272+
bundles: [
273+
{
274+
entryPoint: "./example.scss",
275+
target: "output/example.css"
276+
},
277+
{
278+
entryPoint: "./example2.scss",
279+
target: "output/subfolder/example2.css"
280+
}
281+
]
282+
}
283+
};
284+
```
285+
286+
### Configuration for file watching
287+
288+
You don't need to configure anything for file watching. If you, however, want to
289+
be gentle your file watching limit and your notebook charge, you might want to
290+
restrict file watching to certain folders. Per default, it watches the entire
291+
folder the config file is in. The configuration expects an array of strings. The
292+
strings are paths relative to your configuration file. It could look like this:
293+
294+
```js
295+
module.exports = {
296+
// ...
297+
watchDirs: ["src", "lib"]
298+
}
299+
```
300+
301+
## Sponsors & Users
302+
303+
The work on this project is sponsored by [innoQ](https://www.innoq.com) &
304+
[fejo.dk](https://www.fejo.dk). It is used in production by the following
305+
projects:
306+
307+
* [fejo.dk](https://www.fejo.dk)
308+
309+
## Background
310+
311+
For a while now, we've been advocating ES6 as we've become increasingly
312+
convinced that it helps reduce cognitive load for JavaScript developers, thus
313+
making code both more legible and modular.
314+
315+
However, even modern browsers don't fully
316+
[support](http://kangax.github.io/compat-table/es6/) all the new features yet,
317+
so getting started can be a bit daunting: We need a preprocessor
318+
("[transpiler](https://en.wikipedia.org/wiki/Source-to-source_compiler)") to
319+
translate ES6 into the more universally supported ES5 and also to combine
320+
individual source-code modules into a single bundle. Unfortunately, getting this
321+
right is often tricky — so much so that a commonly encountered sentiment is
322+
"I'd like to use ES6, but haven't set up a transpiler yet".
323+
324+
Similarly, CSS preprocessors like Sass can provide the same benefits for the
325+
styling side of web development, but can also be a hassle to set up.
326+
327+
In order to simplify the process, faucet takes care of all the minutiae,
328+
providing the underlying infrastructure and reducing configuration to the bare
329+
minimum required. With all that out of the way, we can focus on actually writing
330+
the code. Thus we can easily recommend it to friends and colleagues and get them
331+
started in less than a minute.
332+
333+
## Troubleshooting / Frequently Asked Questions (FAQ)
334+
335+
Q: error when importing a third-party library
336+
337+
this typically happens when importing a module which has already been bundled or
338+
otherwise provides a distribution - the solution is to skip transpilation there:
339+
340+
```javascript
341+
import jQuery from "jquery";
342+
```
343+
```javascript
344+
transpiler: {
345+
346+
exclude: ["jquery"]
347+
}
348+
```
349+
350+
(NB: faucet assumes we're consuming ES6 modules by default)
351+
352+
Q: error (ENOSPC) when doing file watching on Linux
353+
354+
You probably reached the maximum value for watched files in inotify. This is
355+
probably due to your `node_modules` folder. You should restrict your watcher to
356+
only the folders that contain your SCSS/JS source files. [More
357+
information](#configuration-for-file-watching)
358+
359+
## License
360+
361+
faucet-pipeline is licensed under Apache 2.0 License.

0 commit comments

Comments
 (0)