147 lines
4.2 KiB
JavaScript
147 lines
4.2 KiB
JavaScript
'use strict'
|
|
|
|
const path = require('path')
|
|
const fs = require('fs')
|
|
const webpack = require('webpack')
|
|
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
|
|
const TerserPlugin = require('terser-webpack-plugin')
|
|
|
|
const getFallbackEnvs = ({ fallbacks, basedir, id, pageExtensions }) => {
|
|
let { document, data } = fallbacks
|
|
|
|
if (!document) {
|
|
let pagesDir = undefined
|
|
|
|
if (fs.existsSync(path.join(basedir, 'pages'))) {
|
|
pagesDir = path.join(basedir, 'pages')
|
|
} else if (fs.existsSync(path.join(basedir, 'src', 'pages'))) {
|
|
pagesDir = path.join(basedir, 'src', 'pages')
|
|
}
|
|
|
|
if (!pagesDir) return
|
|
|
|
const offlines = pageExtensions
|
|
.map(ext => path.join(pagesDir, `_offline.${ext}`))
|
|
.filter(entry => fs.existsSync(entry))
|
|
if (offlines.length === 1) {
|
|
document = '/_offline'
|
|
}
|
|
}
|
|
|
|
if (data && data.endsWith('.json')) {
|
|
data = path.posix.join('/_next/data', id, data)
|
|
}
|
|
|
|
const envs = {
|
|
__PWA_FALLBACK_DOCUMENT__: document || false,
|
|
__PWA_FALLBACK_IMAGE__: fallbacks.image || false,
|
|
__PWA_FALLBACK_AUDIO__: fallbacks.audio || false,
|
|
__PWA_FALLBACK_VIDEO__: fallbacks.video || false,
|
|
__PWA_FALLBACK_FONT__: fallbacks.font || false,
|
|
__PWA_FALLBACK_DATA__: data || false
|
|
}
|
|
|
|
if (Object.values(envs).filter(v => !!v).length === 0) return
|
|
|
|
console.log('> [PWA] Fallback to precache routes when fetch failed from cache or network:')
|
|
if (envs.__PWA_FALLBACK_DOCUMENT__) console.log(`> [PWA] document (page): ${envs.__PWA_FALLBACK_DOCUMENT__}`)
|
|
if (envs.__PWA_FALLBACK_IMAGE__) console.log(`> [PWA] image: ${envs.__PWA_FALLBACK_IMAGE__}`)
|
|
if (envs.__PWA_FALLBACK_AUDIO__) console.log(`> [PWA] audio: ${envs.__PWA_FALLBACK_AUDIO__}`)
|
|
if (envs.__PWA_FALLBACK_VIDEO__) console.log(`> [PWA] video: ${envs.__PWA_FALLBACK_VIDEO__}`)
|
|
if (envs.__PWA_FALLBACK_FONT__) console.log(`> [PWA] font: ${envs.__PWA_FALLBACK_FONT__}`)
|
|
if (envs.__PWA_FALLBACK_DATA__) console.log(`> [PWA] data (/_next/data/**/*.json): ${envs.__PWA_FALLBACK_DATA__}`)
|
|
|
|
return envs
|
|
}
|
|
|
|
const buildFallbackWorker = ({ id, fallbacks, basedir, destdir, minify, pageExtensions }) => {
|
|
const envs = getFallbackEnvs({ fallbacks, basedir, id, pageExtensions })
|
|
if (!envs) return
|
|
|
|
const name = `fallback-${id}.js`
|
|
const fallbackJs = path.join(__dirname, `fallback.js`)
|
|
|
|
webpack({
|
|
mode: 'none',
|
|
target: 'webworker',
|
|
entry: {
|
|
main: fallbackJs
|
|
},
|
|
resolve: {
|
|
extensions: ['.js'],
|
|
fallback: {
|
|
module: false,
|
|
dgram: false,
|
|
dns: false,
|
|
path: false,
|
|
fs: false,
|
|
os: false,
|
|
crypto: false,
|
|
stream: false,
|
|
http2: false,
|
|
net: false,
|
|
tls: false,
|
|
zlib: false,
|
|
child_process: false
|
|
}
|
|
},
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: /\.js$/i,
|
|
use: [
|
|
{
|
|
loader: 'babel-loader',
|
|
options: {
|
|
presets: [
|
|
[
|
|
'next/babel',
|
|
{
|
|
'transform-runtime': {
|
|
corejs: false,
|
|
helpers: true,
|
|
regenerator: false,
|
|
useESModules: true
|
|
},
|
|
'preset-env': {
|
|
modules: false,
|
|
targets: 'chrome >= 56'
|
|
}
|
|
}
|
|
]
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
output: {
|
|
path: destdir,
|
|
filename: name
|
|
},
|
|
plugins: [
|
|
new CleanWebpackPlugin({
|
|
cleanOnceBeforeBuildPatterns: [path.join(destdir, 'fallback-*.js'), path.join(destdir, 'fallback-*.js.map')]
|
|
}),
|
|
new webpack.EnvironmentPlugin(envs)
|
|
],
|
|
optimization: minify
|
|
? {
|
|
minimize: true,
|
|
minimizer: [new TerserPlugin()]
|
|
}
|
|
: undefined
|
|
}).run((error, status) => {
|
|
if (error || status.hasErrors()) {
|
|
console.error(`> [PWA] Failed to build fallback worker`)
|
|
console.error(status.toString({ colors: true }))
|
|
process.exit(-1)
|
|
}
|
|
})
|
|
|
|
return { fallbacks, name, precaches: Object.values(envs).filter(v => !!v) }
|
|
}
|
|
|
|
module.exports = buildFallbackWorker
|