@quasar/app-webpack
Version:
Quasar Framework App CLI with Webpack
172 lines (140 loc) • 5.34 kB
JavaScript
const {
createWebpackChain,
extendWebpackChain,
createBrowserEsbuildConfig,
extendEsbuildConfig
} = require('../../config-tools.js')
const { log } = require('../../utils/logger.js')
const { PwaManifestPlugin } = require('./plugin.webpack.pwa-manifest.js')
const { injectWebpackHtml } = require('../../utils/html-template.js')
const { escapeRegexString } = require('../../utils/escape-regex-string.js')
function injectWebpackPwa(webpackChain, quasarConf) {
const { ctx } = quasarConf
// must be first plugin because it fills in quasarConf.htmlVariables.pwaManifest
// which is later used by injectWebpackHtml()
webpackChain.plugin('pwa-manifest').use(PwaManifestPlugin, [quasarConf])
const opts = {}
const pluginMode = quasarConf.pwa.workboxMode
if (ctx.dev === true) {
// dev resources are not optimized (contain maps, unminified code)
// so they might be larger than the default maximum size for caching
opts.maximumFileSizeToCacheInBytes = Number.MAX_SAFE_INTEGER
}
if (pluginMode === 'GenerateSW') {
Object.assign(opts, {
sourcemap: quasarConf.build.sourcemap !== false,
mode:
quasarConf.metaConf.debugging === true ||
quasarConf.build.minify === false
? 'development'
: 'production',
cacheId: ctx.pkg.appPkg.name || 'quasar-pwa-app',
cleanupOutdatedCaches: true,
clientsClaim: true,
skipWaiting: true
})
if (ctx.dev === true && quasarConf.build.ignorePublicFolder === true) {
// we don't have a public folder, so we can't use the glob* props,
// but then we need a runtime caching at least
opts.runtimeCaching = [
{
urlPattern: `${quasarConf.build.publicPath || '/'}${quasarConf.pwa.manifestFilename}`,
handler: 'NetworkFirst',
options: {
cacheName: 'static-manifest',
expiration: {
maxEntries: 4,
maxAgeSeconds: 60 * 60
}
}
}
]
}
if (ctx.prod === true) {
opts.navigateFallback =
ctx.mode.ssr === true
? quasarConf.ssr.pwaOfflineHtmlFilename
: quasarConf.build.htmlFilename
opts.navigateFallbackDenylist = [
new RegExp(escapeRegexString(quasarConf.pwa.swFilename) + '$'),
/workbox-(.)*\\.js$/
]
} else {
// no one to serve workbox files if they are externalized
opts.inlineWorkboxRuntime = true
}
if (typeof quasarConf.pwa.extendGenerateSWOptions === 'function') {
quasarConf.pwa.extendGenerateSWOptions(opts)
}
opts.swDest = quasarConf.pwa.swFilename
log(
'[GenerateSW] Will generate a service-worker file. Ignoring your custom written one.'
)
} else {
if (typeof quasarConf.pwa.extendInjectManifestOptions === 'function') {
quasarConf.pwa.extendInjectManifestOptions(opts)
}
opts.swSrc = ctx.appPaths.resolve.entry('compiled-custom-sw.js')
opts.swDest = quasarConf.pwa.swFilename
opts.compileSrc = false // don't use Webpack to compile it again
if (typeof quasarConf.pwa.extendInjectManifestOptions === 'function') {
quasarConf.pwa.extendInjectManifestOptions(opts)
}
log('[InjectManifest] Using your custom service-worker written file')
}
if (ctx.mode.ssr) {
if (pluginMode === 'GenerateSW') {
if (typeof quasarConf.ssr.pwaExtendGenerateSWOptions === 'function') {
quasarConf.ssr.pwaExtendGenerateSWOptions(opts)
}
} else if (
typeof quasarConf.ssr.pwaExtendInjectManifestOptions === 'function'
) {
quasarConf.ssr.pwaExtendInjectManifestOptions(opts)
}
opts.exclude = opts.exclude || []
opts.exclude.push('../quasar.manifest.json')
}
const WorkboxPlugin = ctx.cacheProxy.getModule('workboxWebpackPlugin')
webpackChain.plugin('workbox').use(WorkboxPlugin[pluginMode], [opts])
}
module.exports.injectWebpackPwa = injectWebpackPwa
const quasarPwaConfig = {
webpack: async quasarConf => {
const webpackChain = await createWebpackChain(quasarConf, {
compileId: 'webpack-pwa',
threadName: 'PWA UI'
})
injectWebpackPwa(webpackChain, quasarConf)
injectWebpackHtml(webpackChain, quasarConf)
return extendWebpackChain(webpackChain, quasarConf, { isClient: true })
},
// used by ssr-config.js as well
customSw: async quasarConf => {
const { ctx } = quasarConf
const { appPaths } = ctx
const cfg = await createBrowserEsbuildConfig(quasarConf, {
compileId: 'browser-custom-sw'
})
const fallbackHtmlFile =
quasarConf.build.publicPath +
(ctx.mode.ssr === true && ctx.prod === true
? quasarConf.ssr.pwaOfflineHtmlFilename
: quasarConf.build.htmlFilename)
cfg.define['process.env.PWA_FALLBACK_HTML'] =
JSON.stringify(fallbackHtmlFile)
cfg.define['process.env.PWA_SERVICE_WORKER_REGEX'] = JSON.stringify(
`${escapeRegexString(quasarConf.pwa.swFilename)}$`
)
cfg.entryPoints = [quasarConf.sourceFiles.pwaServiceWorker]
cfg.outfile = appPaths.resolve.entry('compiled-custom-sw.js')
return extendEsbuildConfig(
cfg,
quasarConf.pwa,
ctx,
'extendPWACustomSWConf'
)
}
}
module.exports.quasarPwaConfig = quasarPwaConfig
module.exports.modeConfig = quasarPwaConfig