我们正在尝试托管 PWA nuxt,服务工作人员将仅使用 localhost:3000 进行注册
npm start
尝试从 192.168.0.2:3000 访问它会导致以下情况:
页面不是从安全来源提供的 没有匹配的服务工作者 检测到。您可能需要重新加载页面,或检查范围 当前页面的 Service Worker 包含范围并开始 清单中的 URL。
nuxt.config.js
export default {
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'ONX',
htmlAttrs: {
lang: 'en'
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' },
{ name: 'format-detection', content: 'telephone=no' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
//{src: '~/plugins/VueCtkDateTimePicker.js', ssr: false }, // datepicker plugin here
{ src: '~/plugins/DateTimePicker.js' },
{ src: '~/plugins/VueTabulator.js', mode: 'client', ssr: false }
// { src: '~/plugins/Filters.js' }
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
'@nuxtjs/device',
'@nuxtjs/pwa',
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
// https://go.nuxtjs.dev/bootstrap
'bootstrap-vue/nuxt',
'@nuxtjs/axios',
'@nuxtjs/proxy',
'@nuxt/content',
],
proxy: {
'/api': {
target: 'http://target:81',
pathRewrite: {
'^/api': '/',
},
},
changeOrigin: true,
},
bootstrapVue: {
// Install the `IconsPlugin` plugin (in addition to `BootstrapVue` plugin)
icons: true
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
extend(config, ctx) {
if (ctx.isDev) {
config.devtool = ctx.isClient ? 'source-map' : 'inline-source-map'
}
},
},
server: {
host: '0.0.0.0',
port: 8000, // default: 3000
},
pwa: {
manifest: {
"short_name": "my_project",
"name": "my_project",
"background_color": "white",
"display": "standalone",
"scope": "/",
"theme_color": "white"
},
}
}
sw.js
importScripts(...[options.workboxURL, ...options.importScripts])
initWorkbox(workbox, options)
workboxExtensions(workbox, options)
precacheAssets(workbox, options)
cachingExtensions(workbox, options)
runtimeCaching(workbox, options)
offlinePage(workbox, options)
routingExtensions(workbox, options)
function getProp(obj, prop) {
return prop.split('.').reduce((p, c) => p[c], obj)
}
function initWorkbox(workbox, options) {
if (options.config) {
// Set workbox config
workbox.setConfig(options.config)
}
if (options.cacheNames) {
// Set workbox cache names
workbox.core.setCacheNameDetails(options.cacheNames)
}
if (options.clientsClaim) {
// Start controlling any existing clients as soon as it activates
workbox.core.clientsClaim()
}
if (options.skipWaiting) {
workbox.core.skipWaiting()
}
if (options.cleanupOutdatedCaches) {
workbox.precaching.cleanupOutdatedCaches()
}
if (options.offlineAnalytics) {
// Enable offline Google Analytics tracking
workbox.googleAnalytics.initialize()
}
}
function precacheAssets(workbox, options) {
if (options.preCaching.length) {
workbox.precaching.precacheAndRoute(options.preCaching, options.cacheOptions)
}
}
function runtimeCaching(workbox, options) {
const requestInterceptor = {
requestWillFetch({ request }) {
if (request.cache === 'only-if-cached' && request.mode === 'no-cors') {
return new Request(request.url, { ...request, cache: 'default', mode: 'no-cors' })
}
return request
},
fetchDidFail(ctx) {
ctx.error.message =
'[workbox] Network request for ' + ctx.request.url + ' threw an error: ' + ctx.error.message
console.error(ctx.error, 'Details:', ctx)
},
handlerDidError(ctx) {
ctx.error.message =
`[workbox] Network handler threw an error: ` + ctx.error.message
console.error(ctx.error, 'Details:', ctx)
return null
}
}
for (const entry of options.runtimeCaching) {
const urlPattern = new RegExp(entry.urlPattern)
const method = entry.method || 'GET'
const plugins = (entry.strategyPlugins || [])
.map(p => new (getProp(workbox, p.use))(...p.config))
plugins.unshift(requestInterceptor)
const strategyOptions = { ...entry.strategyOptions, plugins }
const strategy = new workbox.strategies[entry.handler](strategyOptions)
workbox.routing.registerRoute(urlPattern, strategy, method)
}
}
function offlinePage(workbox, options) {
if (options.offlinePage) {
// Register router handler for offlinePage
workbox.routing.registerRoute(new RegExp(options.pagesURLPattern), ({ request, event }) => {
const strategy = new workbox.strategies[options.offlineStrategy]
return strategy
.handle({ request, event })
.catch(() => caches.match(options.offlinePage))
})
}
}
function workboxExtensions(workbox, options) {
}
function cachingExtensions(workbox, options) {
}
function routingExtensions(workbox, options) {
}
manifest.json - 在 chrome 调试器上可见
{
"name": "my_project",
"short_name": "my_project",
"icons": [
{
"src": "/_nuxt/icons/icon_64x64.64bc82.png",
"sizes": "64x64",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/_nuxt/icons/icon_120x120.64bc82.png",
"sizes": "120x120",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/_nuxt/icons/icon_144x144.64bc82.png",
"sizes": "144x144",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/_nuxt/icons/icon_152x152.64bc82.png",
"sizes": "152x152",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/_nuxt/icons/icon_192x192.64bc82.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/_nuxt/icons/icon_384x384.64bc82.png",
"sizes": "384x384",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/_nuxt/icons/icon_512x512.64bc82.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
}
],
"start_url": "/?standalone=true",
"display": "standalone",
"background_color": "white",
"theme_color": "white",
"lang": "en",
"scope": "/"
}
对于任何可能面临此问题的人,@Lawrence Cherone 的评论是正确的;我需要一个有效的证书。 如何使用 MKCert 生成本地证书。
安装MKcert并将其添加到本地根CA
mkcert -install
为本地应用程序创建证书(在应用程序运行的文件夹中)
mkcert 192.168.0.2
将证书添加到
nuxt.config.js
server: {
https: {
key: fs.readFileSync(path.resolve(__dirname, '192.168.0.2-key.pem')),
cert: fs.readFileSync(path.resolve(__dirname, '192.168.0.2.pem'))
},
}
清理浏览器cookies和缓存
访问
https://192.168.0.2
,等等:可以安装 PWA 添加了
奖励:对于尝试让它在移动设备上运行的人:
将您的
rootCA.pem
转换为 rootCA.crt
。 如何将pem转换为crt:
openssl x509 -outform der -in rootCA.pem -out rootCA.crt
将
crt
证书导入到您的移动设备。 如何在安卓手机上导入CRT。 (可能因设备而异。)