npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

gulp-spa

v0.2.2

Published

Define your build sources in HTML.

Downloads

44

Readme

gulp-spa

Build Status Coverage Status

gulp-spa is a gulp plugin for making it easier to build single page apps. It lets you define your sources in HTML and the pipelines in gulp so you can easily make different versions, like completely minified and garbled production version, or a development version with the files as they were. It also uses streams for going through the sources, so it's fast!

Installation

You can install gulp-spa via npm:

$ npm install --save-dev gulp-spa

Usage

Include the plugin:

var spa = require("gulp-spa");

This will give you an interface with a method html that takes the following options as its first argument:

  • assetsDir (defaults to ./) This is where gulp-spa will look for the assets your HTML file refers to.
  • pipelines (defaults to {}) A key-value mapping of pipeline names and functions that return the streams the files in that pipeline should go to. The first argument of the function is a stream of the source files.

Defining builds

You define your builds in HTML using the following syntax:

<!-- build:PIPELINE_ID_HERE -->
<script src="foo.js"></script>
<script src="bar.js"></script>
<!-- endbuild -->

So the assets go within the two comment blocks, and you define the name of the pipeline after the build: instruction. Simple, right?

Examples

If you have the following HTML:

<html>
<head>
    <!-- build:css -->
    <link rel="stylesheet" href="foo.css">
    <link rel="stylesheet" href="bar.css">
    <!-- endbuild -->
</head>
<body>
    <!-- build:js -->
    <script src="foo.js"></script>
    <script src="bar.js"></script>
    <!-- endbuild -->
</body>
</html>

and something like this in your gulpfile:

gulp.task("build", function () {
    return gulp.src("./path/to/index.html")
        .pipe(spa.html({
            assetsDir: "./path/to/",
            pipelines: {
                main: function (files) {
                    // this gets applied for the HTML file itself
                    return files.pipe(htmlmin());
                },

                js: function (files) {
                    return files
                        .pipe(uglify())
                        .pipe(concat("app.js"))
                        .pipe(rev());
                },

                css: function (files) {
                    return files
                        .pipe(minifyCss())
                        .pipe(concat("app.css")
                        .pipe(rev());
                }
            }
        })))
        .pipe(gulp.dest("./public/"));
});

You will end up with your files minified, revved and whatnot, and something like the following HTML:

<html>
<head>
    <link rel="stylesheet" href="app-f71237f1.css">
</head>
<body>
    <script src="app-ead18fa.js"></script>
</body>
</html>

Because gulp-spa uses vinyl-fs (the same module that provides gulp.src and gulp.dest) itself for finding the files, and streams for processing, it even gives you the flexibility to go crazy like this:

<html>
<head>
    <!-- build:css -->
    <link rel="stylesheet" href="**/*.styl">
    <!-- endbuild -->
</head>
<body>
    <!-- build:js -->
    <script src="**/*.coffee"></script>
    <!-- endbuild -->
</body>
</html>
gulp.task("build", function () {
    return gulp.src("./path/to/index.html")
        .pipe(spa.html({
            assetsDir: "./path/to/",
            pipelines: {
                js: function (files) {
                    return files
                        .pipe(coffee());
                },

                css: function (files) {
                    return files
                        .pipe(stylus());
                }
            }
        })))
        .pipe(gulp.dest("./public/"));
});

And it will work as expected:

<html>
<head>
    <link rel="stylesheet" href="used-to-be-stylus-1.css">
    <link rel="stylesheet" href="used-to-be-stylus-2.css">
</head>
<body>
    <script src="used-to-be-coffee-script-1.js"></script>
    <script src="used-to-be-coffee-script-2.js"></script>
</body>
</html>

If you want to define your sources in your gulpfile, for example to use the same list of sources for tests, you can do that as well. This is done by not defining any sources in the build, and defining them in the pipeline stream instead:

<html>
<body>
    <!-- build:js -->
    <!-- endbuild -->
</body>
</html>
gulp.task("build", function () {
    return gulp.src("./path/to/index.html")
        .pipe(spa.html({
            pipelines: {
                js: function () {
                    return gulp.src("./path/to/javascripts/*.js")
                        .pipe(concat("app.js"));
                }
            }
        })))
        .pipe(gulp.dest("./public/"));
});

If you wanted to have leading slashes in front of your URLs, you can do that by either having one in your source files:

<html>
<body>
    <!-- build:js -->
    <script src="/my-js-file1.js"></script>
    <script src="/my-js-file2.js"></script>
    <!-- endbuild -->
</body>
</html>

Or you can also define it by overriding the build options:

<html>
<body>
    <!-- build:js {
        "urlPrefix": "/"
    } -->
    <script src="my-js-file1.js"></script>
    <script src="my-js-file2.js"></script>
    <!-- endbuild -->
</body>
</html>

If you wanted to be able to define your own URLs, you can do that by defining them in your build options:

<html>
<body>
    <!-- build:js {
        "urlPrefix": "/your-choosen-path/"
    } -->
    <script src="my-js-file1.js"></script>
    <script src="my-js-file2.js"></script>
    <!-- endbuild -->
</body>
</html>

urlPrefix can be whatever valid string you need (paths, urls) and will be prepended to your generated file name.

<script src="/your-choosen-path/generated-file.js"></script>

Inspiration and Philosophy

gulp-spa draws its inspiration from grunt-usemin. What I wanted to do is split what usemin does (a lot of things!) and make them into small components that do one thing and do it well. Another part of that project is gulp-resolver that replaces references to original assets by finding the minified / revved files generated by the build.

As mentioned, the philosophy behind the plugin is to do one thing and do it well. Other than that, I'm a big fan of node streams and fast builds, so high performance and building on streams are high up on the design goal list.

Future

For now, only HTML is supported, with assets that compile to / are JS or CSS, but in the future I hope to fix that. The problem is, I can't think of the perfect API to suit that purpose, so if you have ideas, go ahead and file an issue!

Contributing

Contributions are most welcome! If you're having problems and don't know why, search the issues to see if someone's had the same issue. If not, file a new issue so we can solve it together and leave the solution visible to others facing the same problem as well. If you find bugs, file an issue, preferably with good reproduction steps. If you want to be totally awesome, you can make a PR to go with your issue, containing a new test case that fails currently!

Development

Development is pretty straightforward, it's all JS and the standard node stuff works:

To install dependencies:

$ npm install

To run the tests:

$ npm test

Then just make your awesome feature and a PR for it. Don't forget to file an issue first, or start with an empty PR so others can see what you're doing and discuss it so there's a a minimal amount of wasted effort.

Do note that the test coverage is currently a whopping 100%. Let's keep it that way! Remember: if it's not in the requirements specification (i.e. the tests), it's not needed, and thus unnecessary bloat.