Skip to content

Commit

Permalink
Generate multiple html documents and inline the relevant scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
theninthsky committed Nov 6, 2022
1 parent 486fbf1 commit 960e789
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 48 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"start": "webpack serve --mode development",
"prebuild": "npm-run-all -p fetch-static create-sitemap",
"build": "webpack --mode production",
"postbuild": "node scripts/create-404.mjs",
"serve": "serve build",
"fetch-static": "node scripts/fetch-static.mjs",
"create-sitemap": "node scripts/create-sitemap.mjs"
Expand Down
38 changes: 9 additions & 29 deletions public/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = pages => `
module.exports = ({ path, scripts, data }) => `
<!DOCTYPE html>
<html lang="en">
<head>
Expand All @@ -14,60 +14,40 @@ module.exports = pages => `
<title>Client-side Rendering</title>
<script>
const isStructureEqual = (pathname, path) => {
pathname = pathname.split('/')
path = path.split('/')
if (pathname.length !== path.length) return false
return pathname.every((segment, ind) => segment === path[ind] || path[ind].includes(':'))
}
let { pathname } = window.location
if (pathname !== '/') pathname = pathname.replace(/\\/$/, '')
const pages = ${JSON.stringify(pages)}
const path = '${path}'
const data = ${JSON.stringify(data)}
for (const { path, scripts, data } of pages) {
const match = pathname === path || (path.includes(':') && isStructureEqual(pathname, path))
if (!match) continue
scripts.forEach(script => {
document.head.appendChild(
Object.assign(document.createElement('link'), { rel: 'preload', href: '/' + script, as: 'script' })
)
})
if (!data) break
if (data) {
data.forEach(({ url, dynamicPathIndexes, crossorigin, preconnectURL }) => {
let fullURL = url
if (dynamicPathIndexes) {
const pathnameArr = pathname.split('/')
const dynamics = dynamicPathIndexes.map(index => pathnameArr[index])
let counter = 0
fullURL = url.replace(/\\$/g, match => dynamics[counter++])
}
document.head.appendChild(
Object.assign(document.createElement('link'), { rel: 'preload', href: fullURL, as: 'fetch', crossOrigin: crossorigin })
)
if (preconnectURL) {
document.head.appendChild(
Object.assign(document.createElement('link'), { rel: 'preconnect', href: preconnectURL })
)
}
})
break
}
</script>
${scripts.map(({ name, source }) => `<script id="${name}" type="module">${source}</script>`).join('\n')}
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
5 changes: 0 additions & 5 deletions public/serve.json

This file was deleted.

3 changes: 3 additions & 0 deletions scripts/create-404.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { copyFileSync } from 'fs'

copyFileSync('build/index.html', 'build/404.html')
30 changes: 16 additions & 14 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ module.exports = (_, { mode }) => {
port: 3000,
devMiddleware: { stats: 'errors-warnings' }
},
cache: { type: 'filesystem' },
devtool: production ? 'source-map' : 'inline-source-map',
resolve: {
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
Expand Down Expand Up @@ -91,22 +90,25 @@ module.exports = (_, { mode }) => {
...(production ? [] : [new ReactRefreshPlugin()]),
...(production ? [] : [new ForkTsCheckerPlugin()]),
new ESLintPlugin(),
new HtmlPlugin({
scriptLoading: 'module',
templateContent: ({ compilation }) => {
const assets = compilation.getAssets().map(({ name }) => name)
...pagesManifest.map(
({ chunk, path, data }) =>
new HtmlPlugin({
filename: `${path.slice(1).replace(':', '') || 'index'}.html`,
inject: false,
templateContent: ({ htmlWebpackPlugin, compilation }) => {
const assets = compilation.getAssets()
const mainAssets = htmlWebpackPlugin.files.js.map(file => decodeURIComponent(file).slice(1))
const scripts = [
...assets.filter(({ name }) => mainAssets.includes(name)),
...assets.filter(({ name }) => new RegExp(`[/.]${chunk}\\.(.+)\\.js$`).test(name))
].map(({ name, source }) => ({ name, source: source._children[0]._value }))

const pages = pagesManifest.map(({ chunk, path, data }) => {
const scripts = assets.filter(name => new RegExp(`[/.]${chunk}\\.(.+)\\.js$`).test(name))
if (data && !Array.isArray(data)) data = [data]

if (data && !Array.isArray(data)) data = [data]

return { path, scripts, data }
return htmlTemplate({ path, scripts, data })
}
})

return htmlTemplate(pages)
}
}),
),
new CopyPlugin({
patterns: [
{
Expand Down

0 comments on commit 960e789

Please sign in to comment.