123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- '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
|