All Projects → GoogleChromeLabs → Prerender Loader

GoogleChromeLabs / Prerender Loader

Licence: apache-2.0
📰 Painless universal pre-rendering for Webpack.

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Prerender Loader

Prerender Spa Plugin
Prerenders static HTML in a single-page application.
Stars: ✭ 7,018 (+267.82%)
Mutual labels:  webpack, prerender
Ng Static Site Generator
ng-static-site-generator is a webpack-based command line build tool that builds an Angular app and Jekyll-style blog entry html files into a static html and css website. It also supports building a client app so you can have static pages that are also capable of running dynamic functionality coded in Angular.
Stars: ✭ 42 (-97.8%)
Mutual labels:  webpack, prerender
Html Webpack Plugin
Simplifies creation of HTML files to serve your webpack bundles
Stars: ✭ 9,942 (+421.07%)
Mutual labels:  webpack, html-webpack-plugin
File Loader
File Loader
Stars: ✭ 1,846 (-3.25%)
Mutual labels:  webpack
Blog
浩麟的技术博客
Stars: ✭ 2,002 (+4.93%)
Mutual labels:  webpack
Webpack Fast Refresh
React Fast Refresh plugin and loader for webpack
Stars: ✭ 155 (-91.88%)
Mutual labels:  webpack
Deventy
A minimal 11ty starting point for building static websites with modern tools.
Stars: ✭ 157 (-91.77%)
Mutual labels:  webpack
Clean Webpack Plugin
By default, this plugin will remove all files inside webpack's output.path directory, as well as all unused webpack assets after every successful rebuild.
Stars: ✭ 1,888 (-1.05%)
Mutual labels:  webpack
Angular Electron
Angular2 and Electron starter using webpack
Stars: ✭ 155 (-91.88%)
Mutual labels:  webpack
Webpackstudydemo
Webpack learning journal and awesome resources.
Stars: ✭ 154 (-91.93%)
Mutual labels:  webpack
Goa
基于Beego开发的问答系统
Stars: ✭ 154 (-91.93%)
Mutual labels:  webpack
Terminal In React
👨‍💻 A component that renders a terminal
Stars: ✭ 1,939 (+1.62%)
Mutual labels:  webpack
Webpack Encore
A simple but powerful API for processing & compiling assets built around Webpack
Stars: ✭ 1,975 (+3.51%)
Mutual labels:  webpack
Babel Plugin Webpack Alias
babel 6 plugin which allows to use webpack resolve options
Stars: ✭ 151 (-92.09%)
Mutual labels:  webpack
Reactconfbr
Public infos and issues about React Conf Brasil organization
Stars: ✭ 156 (-91.82%)
Mutual labels:  webpack
Reactql
Universal React+GraphQL starter kit: React 16, Apollo 2, MobX, Emotion, Webpack 4, GraphQL Code Generator, React Router 4, PostCSS, SSR
Stars: ✭ 1,833 (-3.93%)
Mutual labels:  webpack
J
微信网页版API 微信桌面机器人
Stars: ✭ 155 (-91.88%)
Mutual labels:  webpack
Awesome Web You Should Know
🌎awesome web you should know
Stars: ✭ 154 (-91.93%)
Mutual labels:  webpack
Pychat
webchat via WebSockets/WebRTC that allows messaging/video call/screen sharing
Stars: ✭ 152 (-92.03%)
Mutual labels:  webpack
React Webpack 5 Tailwind 2
React 17 Boilerplate with Webpack 5, Tailwind 2, using babel, SASS/PostCSS, HMR, dotenv and an optimized production build
Stars: ✭ 155 (-91.88%)
Mutual labels:  webpack

prerender-loader

prerender-loader npm

Painless universal prerendering for Webpack. Works great with html-webpack-plugin.

🧐 What is Prerendering?

Pre-rendering describes the process of rendering a client-side application at build time, producing useful static HTML that can be sent to the browser instead of an empty bootstrapping page.

Pre-rendering is like Server-Side Rendering, just done at build time to produce static files. Both techniques help get meaningful content onto the user's screen faster.

Features

  • Works entirely within Webpack
  • Integrates with html-webpack-plugin
  • Works with webpack-dev-server / webpack serve
  • Supports both DOM and String prerendering
  • Asynchronous rendering via async/await or Promises

How does it work?

prerender-loader renders your web application within Webpack during builds, producing static HTML. When the loader is applied to an HTML file, it creates a DOM structure from that HTML, compiles the application, runs it within the DOM and serializes the result back to HTML.


Installation

First, install prerender-loader as a development dependency:

npm i -D prerender-loader

Usage

In most cases, you'll want to apply the loader to your html-webpack-plugin template option:

// webpack.config.js
module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
-     template: 'index.html',
+     template: '!!prerender-loader?string!index.html',

      // any other options you'd normally set are still supported:
      compile: false,
      inject: true
    })
  ]
}

What does all that punctuation mean? Let's break the whole loader string down:

In Webpack, a module identifier beginning with !! will bypass any configured loaders from module.rules - here we're saying "don't do anything to index.html except what I've defined here

The ?string parameter tells prerender-loader to output an ES module exporting the prerendered HTML string, rather than returning the HTML directly.

Finally, everything up to the last ! in a module identifier is the inline loader definition (the transforms to apply to a given module). The filename of the module to load comes after the !.

Note: If you've already set up html-loader or raw-loader to handle .html files, you can skip both options and simply pass a template value of "prerender-loader!index.html"!

As with any loader, it is also possible to apply prerender-loader on-the-fly :

const html = require('prerender-loader?!./app.html');

... or in your Webpack configuration's module.rules section:

module.exports = {
  module: {
    rules: [
      {
        test: 'src/index.html',
        loader: 'prerender-loader?string'
      }
    ]
  }
}

Once you have prerender-loader in-place, prerendering is now turned on. During your build, the app will be executed, with any modifications it makes to index.html will be saved to disk. This is fine for the needs of many apps, but you can also take more explicit control over your prerendering: either using the DOM or by rendering to a String.

DOM Prerendering

During prerendering, your application gets compiled and run directly under NodeJS, but within a JSDOM container so that you can use the familiar browser globals like document and window.

Here's an example entry module that uses DOM prerendering:

import { render } from 'fancy-dom-library';
import App from './app';

export default () => {
  render(<App />, document.body);
};

In all cases, asynchronous functions and callbacks are supported:

import { mount } from 'other-fancy-library';
import app from './app';

export default async function prerender() {
  let res = await fetch('https://example.com');
  let data = await res.json();
  mount(app(data), document.getElementById('app'));
}

String Prerendering

It's also possible to export a function from your Webpack entry module, which gives you full control over prerendering: prerender-loader will call the function and its return value will be used as the static HTML. If the exported function returns a Promise, it will be awaited and the resolved value will be used.

import { renderToString } from 'react-dom';
import App from './app';

export default () => {
  const html = renderToString(<App />);
  // returned HTML will be injected into <body>:
  return html;
};

In addition to DOM and String prerendering, it's also possible to use a combination of the two. If an application's Webpack entry exports a prerender function that doesn't return a value, the default DOM serialization will kick in, just like in DOM prerendering. This means you can use your exported prerender function to trigger DOM manipulation ("client-side" rendering), and then just let prerender-loader handle generating the static HTML for whatever got rendered.

Here's an example that renders a Preact application and waits for DOM rendering to settle down before allowing prerender-loader to serialize the document to static HTML:

import { h, options } from 'preact';
import { renderToString } from 'preact';
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 preact 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);
});

Injecting content into the HTML

When applied to a .html file, prerender-loader will inject prerendered content at the end of <body> by default. If you want to place the content somewhere else, you can add a {{prerender}} field:

<html>
  <body>
    <div id="app_root">
      <!-- Inject any pre-rendered HTML here: -->
      {{prerender}}
    </div>
  </body>
</html>

This works well if you intend to provide a prerender function that only returns your application's HTML structure, not the full document's HTML.

Prerendering JavaScript Files

In addition to processing .html files, the loader can also directly pre-render .js scripts. The only difference is that the DOM used for prerender will be initially empty:

const prerenderedHtml = require('!prerender-loader?string!./app.js');

Options

All options are ... optional.

Option Type Default Description
string boolean false Output a JS module exporting an HTML String instead of the HTML itself
disabled boolean false Bypass the loader entirely (but still respect options.string)
documentUrl string 'http://localhost' Change the jsdom's URL (affects window.location, document.URL...)
params object null Options to pass to your prerender function
env object {} Environment variables to define when building JS for prerendering

License

Apache 2.0

This is not an official Google product.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].