0.1.3 • Published 5 years ago

@hungry/webpack-render-static-page-plugin v0.1.3

Weekly downloads
-
License
TBD
Repository
-
Last release
5 years ago

@hungry/webpack-render-static-page-plugin

Plugin for webpack v4 that enables react to generate HTML files to serve your bundles.

Install

yarn add @hungry/webpack-render-static-page-plugin

How

webpack configuration

const config = {
  entry: {
    ...,
    static: 'static.ts'               // see below on example definition
  },
  plugins: [
    renderStaticComponent({
      entry: 'static',                // defined in entries map as static
      component: 'makeIndex',         // method to be called from static entry point
      filename: 'index.static.html',  // filename for index file to be generated
      data: {}                        // some external data, i.e. env vars
    })
  ]
}

Example definition of static page

  • static page has to fulfill StaticComponentRenderer interface defined as follows
interface StaticRenderProps {
  webpackStats: PersistedStats
  env: NodeJS.ProcessEnv
}
import * as React from 'react'
import Helmet, { HelmetProvider } from 'react-helmet-async'
import { renderToString } from 'react-dom/server'
import { StaticComponentRenderer, StaticRenderProps } from '@hungry/webpack-render-static-page-plugin'

export const renderHTML = ({html, env, helmet}) =>
  `<!DOCTYPE html>
   <html ${helmet.htmlAttributes.toString()}>
     <head>
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <meta charset="utf-8" />
      <script>{withServiceWorkerInit}</script>
       ${helmet.noscript.toString()}
       ${helmet.title.toString()}
       ${helmet.meta.toString()}
       ${helmet.link.toString()}
       <script>window.environment = ${JSON.stringify(env)}</script>
     </head>
     <body>
        <body ${helmet.bodyAttributes.toString()}>
         <div id="app">${html}</div>
        </body>
        ${helmet.script.toString()}
     </body>
   </html>
  `

export const SomeNestedPage: React.SFC<StaticRenderProps> = props =>
  <Helmet>
    <title>Hello World</title>
    {cdnLibs.concat(lazyJSLibs).map(makeScriptTag)}
    {css.map(makeCSSTag)}
    <body className="root" />
  </Helmet>

export const makeIndex: StaticComponentRenderer =
  (compilationData) => {
    const context = { ...helmetContext }
    const App = <HelmetProvider context={context}>
      <SomeNestedPage
        webpackStats={compilationData.webpackStats}
        env={compilationData.env}
      />
    </HelmetProvider>

    return Promise.resolve(
      renderHTML(appString, {
        html: renderToString(App),
        helmet: context.helmet,
        env: compilationData.env,
      })
    )
  }

Why

To be able to generate index page based on helmet or helmet-async rather than playing with handlebars or velocity templates. Another goal was to not making webpack config too verbose and make index page testable.

Caveats

This is at stage works for me, so if you've got any troubles, please let me know.