0.0.1 • Published 6 years ago

suprya v0.0.1

Weekly downloads
2
License
MIT
Repository
github
Last release
6 years ago

✨ Features

  • Bundle your app using only a package.json and webpack.config.js
  • Opinionated Webpack defaults for both development and production modes
  • Prerenders all your app routes (via prerender-loader)
  • Everything is configurable (and uses technologies you already know)

🔧 Installation

Install suprya using npm:

npm i -D suprya

The minimum supported Node version is v6.9.0

📦 Usage

Suprya takes your Webpack config as an input and adds its own opinionated config values for the ultimate developer experience. To start, open your webpack.config.js and wrap your exported config with the suprya() function:

const suprya = require('suprya');

const isProduction = process.env.NODE_ENV === 'production';

module.exports = suprya({
  mode: isProduction ? 'production' : 'development',
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader'
      }
    ]
  }
});

Suprya will take care of adding the entry (./src/index.js) and output (defaults to the dist directory) options, adding vendor chunk splitting and applying all the plugins for you. But, don't worry; you can still change all these options if you need more flexibility.

Next, we will add the src/template.html file which will be the base of all the prerendered outputs (but will also be used in development mode):

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
  </head>
  <body>
    <div id="root">
      {{prerender:./src/prerender.js}}
    </div>
  </body>
</html>

As you can see, we've used a Handlebars expression that tells Suprya that the prerendered content (generated by the prerender.js file, which we will create on the next step) needs to be appended under #root.

Thanks to prerender-loader you can either export a String which will be used as the static HTML or automatically render it on the #root element. Depending on what library you're using its contents may vary. Here are some examples:

React app

Suprya supports any kind of router such as react-router or Reach router.

src/prerender.js

import React from 'react';
import { renderToString } from 'react-dom/server';

import App from './components/App';

export default () => renderToString(<App />);

You can also take a look at the example React app on examples/react. It has a README which explains things related to React in greater detail.

Preact app

TODO

Submit your own!

You can add your own library by submitting a PR! :grinning:

Suprya will call your prerender.js default exported function on production for each one of your routes (we take care of setting the right window.location value for you).

Also note that you can export an async function or a Promise in case you might want to wait for the DOM rendering to settle down before allowing Suprya to serialize the document to static HTML:

// Taken from the prerender-loader docs
import { render, options } from 'dom-library';
import App from './App';

// We're done when there are no renders for 50ms:
const IDLE_TIMEOUT = 50;

export default () => new Promise(resolve => {
  let timer;

  // Each time your library re-renders, reset our idle timer:
  options.debounceRendering = commit => {
    clearTimeout(timer);
    timer = setTimeout(resolve, IDLE_TIMEOUT);
    commit();
  }

  // Render into <body> using normal client-side rendering:
  render(<App />, document.body);
})

Everything that's left is telling Suprya about what routes you want to prerender (you might not want to render all of them, but it's recommended) by passing a routes array to the Suprya config. Go to your webpack.config.js file and add the following:

const suprya = require('suprya');

module.exports = suprya({
  routes: [
    {
      url: '/',
      title: 'Home Page'
    },
    {
      url: '/contact',
      title: 'Contact Me'
    }
  ],
  defaultTitle: 'My Awesome App'
  // ...
});

Suprya will now prerender / and /contact on production mode by calling your prerender.js default export to produce the dist/index.html and dist/contact/index.html files.

That's it! You can now run webpack using your preferred CLI. We recommend using the following:

  • webpack-command for bundling your files for production. Here are some useful flags and tips:
    • --bail will stop the build on the first error.
    • --run-prod will apply additional optimizations such as UglifyJS on top of Suprya. (Details)
    • --progress will show a nice progress bar.
    • Don't forget to set NODE_ENV to production (Instructions)
  • webpack-serve for hot reloading your app during development. Here are some useful tips:

🔨 Options

Suprya shares the same configuration object as Webpack, but will remove all its values from the final Webpack config e.g., in order to pass the disabled option you would add the disabled key to your webpack.config.js file as follows:

const suprya = require('suprya');

module.exports = suprya({
  disabled: true,
  // Other Webpack or Suprya options
});
OptionTypeDefaultDescription
routes[{ url, title, meta, ... }]undefinedWhich routes you want to prerender. Each route has a required url key, an optional title and additional html-webpack-plugin options.
defaultTitlestring"Suprya App"The default title used for pages which haven't specified one.
templatePathstring"src/template.html"The location of the HTML template used for prerendering (also used in development mode).
shouldUseSourceMapbooleanmode === 'production'Whether to generate production or development source maps. You can also add the Webpack's devtool option which will override Suprya's choice.
disabledbooleanfalseDisables Suprya entirely (will return the same passed config). Useful for debugging.

✅ Opinionated Webpack options

Suprya is an opinionated static-site generator, but stands to be as flexible as possible, so any settings specified below can be overrided (by setting your preferred value on your webpack.config.js):

Suprya applies these Webpack options on production mode:

OptionValueDescription
entry./src/index.jsWhich module Webpack will use to begin building out its internal dependency graph.
output{ path: 'cwd/dist', filename: 'name.chunkhash.js', publicPath: '/'}Directory where the compiled files will be written.
devtoolsource-mapPlace source maps on a different file (ending in .js.map).
optimization{ splitChunks: { chunks: 'all' }, runtimeChunk: true}Splits vendor dependencies and keeps the runtime chunk separated.

Suprya also applies these Webpack options on development mode:

OptionValueDescription
entry./src/index.jsWhich module Webpack will use to begin building out its internal dependency graph.
output{ path: 'cwd/dist', filename: 'name.chunkhash.js', publicPath: '/'}Directory where the compiled files will be written.
devtoolcheap-module-source-mapGenerate fast (but bigger) source maps.
devServer{ contentBase: 'cwd/public'}Serve static assets from the public directory.
serve[see src/historyApiFallback.js]Applies the historyApiFallback addon.

Additionally, Suprya adds an HtmlWebpackPlugin instance in development mode and multiple ones (to make prerendering possible) on production mode. That means you don't need to add the HtmlWebpackPlugin to your webpack.config.js file.

Note: [cwd] refers to the current working directory i.e. the directory where you run the webpack CLI from.

🛣 Roadmap

  • Inlining the critical CSS and lazy-loading the rest (via Critters)
  • Configless route detection (might involve library specific plugins)
  • Automatic template and prerender.js creation.
  • Prerender all the routes

🥂 License

Suprya is open source software licensed as MIT.