Service Worker registration error: Unsupported MIME type ('text/html')
Service Worker registration error: Unsupported MIME type ('text/html')
我正在使用 create-react-app with an express 服务器。
create-react-app
有一个缓存本地资产 (https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#making-a-progressive-web-app) 的 pre-configured ServiceWorker。
我尝试在我的服务器上发布时遇到的问题是 service-worker.js
文件可用,但当我尝试注册它时我的浏览器控制台出现错误。
在 Firefox 上,我收到此错误:
Error during service worker registration:
TypeError: ServiceWorker script at https://my-domain.com/service-worker.js for scope https://my-domain.com/ encountered an error during installation.
在 Chrome,我得到了更具描述性的错误:
Error during service worker registration: DOMException: Failed to register a ServiceWorker: The script has an unsupported MIME type ('text/html').
果然,如果我查看我的开发人员工具的网络选项卡并搜索 service-worker.js
文件,我可以看到它在 HTTP headers 中有错误的 MIME 类型。
虽然我不明白,为什么它的 MIME 类型错误?
在我的 Express 服务器应用程序中,我有一个重定向到 index.html
:
的通配符(星号/*)路由
// Load React App
// Serve HTML file for production
if (env.name === "production") {
app.get("*", function response(req, res) {
res.sendFile(path.join(__dirname, "public", "index.html"));
});
}
这是一种非常常见的设计模式。但是,这意味着任何对未知文本文件的请求最初都会被重定向到 index.html
,因此 return 的 MIME 类型为 "text/html"
,即使它实际上是 JavaScript 或SVG 或其他类型的纯文本文件。
我找到的解决方案是在通配符路由之前为service-worker.js
添加特定路由:
app.get("/service-worker.js", (req, res) => {
res.sendFile(path.resolve(__dirname, "public", "service-worker.js"));
});
app.get("*", function response(req, res) {
res.sendFile(path.join(__dirname, "public", "index.html"));
});
现在,当浏览器查找 service-worker.js
时,Express 会 return 使用正确的 MIME 类型。
(请注意,如果您尝试在通配符后添加 service-worker.js
路由,它不会起作用,因为通配符路由将被覆盖。)
ServiceWorker 支持的 MIME 类型是 'text/javascript'、application/javascript 和 application/x-javascript。转到您的服务器文件并设置
response.writeHead(201, {
'Content-Type': 'application/javascript'
});
该脚本具有不受支持的 MIME 类型 ('text/html')。
无法加载资源:net::ERR_INSECURE_RESPONSE
(索引):1 未捕获(承诺)DOMException:无法注册 ServiceWorker:脚本具有不受支持的 MIME 类型('text/html')。
template.js 根文件
的代码
export default ({ markup, css }) => {
return `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MERN Marketplace</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<style>
a{
text-decoration: none
}
</style>
<link rel="manifest" href="./manifest.json">
</head>
<body style="margin:0">
<div id="root">${markup}</div>
<style id="jss-server-side">${css}</style>
<script type="text/javascript" src="/dist/bundle.js"></script>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js').then(function() {
console.log("Service Worker Registered");
});
}
</script>
</body>
</html>`;
};
应用此更改:
'/service-worker.js' // ❌
'./service-worker.js' // ✅
解决了我的问题。
(在navigator.serviceWorker.register('/service-worker.js')
)
或者您可能需要:
'%PUBLIC_URL%/serviceworker.js'
感谢@DanielLord for 。
反应:
public/index.html
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('sw-cached-site.js', function() {
navigator.serviceWorker.register('service-worker.js', {
scope: '/',
});
});
}
window.process = { env: { NODE_ENV: 'production' } };
</script>
注:满app/site
public/sw-cached-site.js
const cacheName = 'v1';
self.addEventListener('activate', (e) =>{
e.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cache => {
if(cache !== cacheName) {
return caches.delete(cache);
}
})
)
})
)
});
self.addEventListener('fetch', e => {
e.respondWith(
fetch(e.request)
.then(res => {
const resClone = res.clone();
caches
.open(cacheName)
.then(cache => {
cache.put(e.request, resClone);
});
return res;
}).catch(err => caches.match(e.request).then(res => res))
);
});
确保已生成服务工作者文件(Chrome DevTools -> Sources -> Filesystem)。如果根本没有生成 service worker 文件(检查你的部署脚本),你可能会收到这样的错误。
如果您正在使用 NodeJS,serviceWorker 文件应放在 public 文件夹中。
如果您使用 Webpack 将 serviceWorker 导出到 public,则需要使用 'copy-webpack-plugin'.
我使用 nginx 为 React 应用程序提供服务,我解决了这个问题,将 mime 类型添加到 nginx:
http {
include mime.types; // <--- this line
# another config details
}
你还可以找到mime.types file here
我遇到了同样的问题,从我的配置中删除其他 firebase 库为我解决了这个问题 Check this on Github
// Change this
var firebaseConfig = {
apiKey: "*********",
authDomain: "**********",
databaseURL: "*********",
projectId: "***********",
storageBucket: "************",
messagingSenderId: "***********",
appId: "************"
};
// To =>
var firebaseConfig = {
apiKey: "*****************",
projectId: "**********",
messagingSenderId: "*******",
appId: "***********"
};
我认为 http://localhost:3000/service-worker.js
中不存在服务工作者文件,因此服务器返回 index.html。然后注册功能不知道如何处理 index.html 文件并告诉您 MIME 类型不正确。
一个快速修复方法是将 service-worker.js 文件复制到 public
文件夹,这样当您点击 http://localhost:3000/service-worker.js
时,您就可以在浏览器中看到该文件。
记得转到 ChromeDev > Applications > ServiceWorkers 并点击取消订阅。为了删除错误的。记住还要禁用缓存
就我而言,对于 Vue,我需要使用 command-line 工具在 public 目录中生成 mockServiceWorker.js,如下所述:
https://mswjs.io/docs/getting-started/integrate/browser
我从样本中不清楚这一点。具体到 运行 的 CLI 命令是:
npx msw init ./public
self.addEventListener('fetch', function(event) {});
在您的 service-worker.js 文件中添加以上代码
当 运行 webpack 开发服务器时,它会为缺少的资源呈现默认值 index.html。
如果您使用浏览器加载 http://localhost:3000/sw.js
,您实际上会看到一个呈现的 React 应用程序(由 index.html 启动)。这就是为什么 mime 类型是 html,而不是 javascript。
此回退到 index.html 旨在支持 SPA 和前端路由。例如 /product/123/reviews
在后端没有这样的 html 文件,JS SPA 应用程序在前端处理它。
为什么您的文件丢失了?我猜你在项目的根文件夹中创建了那个文件。
Webpack 开发服务器不从该根文件夹提供服务。
将您的 sw.js 移动到项目的 public/ 文件夹中,它将按预期提供。
我想,service worker 文件应该在根路径上。在我的例子中,我不能使用根路径,所以我使用 apache 重定向规则将 service-worker.js 重定向到我的子路径。
RewriteRule "^/service-worker.js$" "/sub/service-worker.js"
我在使用 python 托管网站时遇到了类似的问题。 None 这里的解决方案对我有用,我遇到了一个 bug posted in chrome dev forum,它设法解决了我的问题。显然,在我的案例中这是 windows 相关的问题,因为 .js 文件的注册表条目的内容类型设置为 text/plain 由于某些先前的配置,我不得不改回 application/javascript。
TLDR:
- 打开注册表编辑器
- 转到Computer\HKEY_CLASSES_ROOT\.js
- 将内容类型更改为 application/javascript
- 重新启动 Chrome 和 运行 您的网站
希望这对某些 none 以上作品有所帮助。
此错误是因为应用程序(在本例中为 Angular)未找到文件 service-worker.js
(ngsw-config.js
或其他名称文件)。
我通过添加 angular.json
:
解决了这个问题
"serviceWorker": true,
"ngswConfigPath": "service-worker.json",
这应该添加到所有配置:例如,生产、测试和暂存。
我正在使用 create-react-app with an express 服务器。
create-react-app
有一个缓存本地资产 (https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#making-a-progressive-web-app) 的 pre-configured ServiceWorker。
我尝试在我的服务器上发布时遇到的问题是 service-worker.js
文件可用,但当我尝试注册它时我的浏览器控制台出现错误。
在 Firefox 上,我收到此错误:
Error during service worker registration:
TypeError: ServiceWorker script at https://my-domain.com/service-worker.js for scope https://my-domain.com/ encountered an error during installation.
在 Chrome,我得到了更具描述性的错误:
Error during service worker registration: DOMException: Failed to register a ServiceWorker: The script has an unsupported MIME type ('text/html').
果然,如果我查看我的开发人员工具的网络选项卡并搜索 service-worker.js
文件,我可以看到它在 HTTP headers 中有错误的 MIME 类型。
虽然我不明白,为什么它的 MIME 类型错误?
在我的 Express 服务器应用程序中,我有一个重定向到 index.html
:
// Load React App
// Serve HTML file for production
if (env.name === "production") {
app.get("*", function response(req, res) {
res.sendFile(path.join(__dirname, "public", "index.html"));
});
}
这是一种非常常见的设计模式。但是,这意味着任何对未知文本文件的请求最初都会被重定向到 index.html
,因此 return 的 MIME 类型为 "text/html"
,即使它实际上是 JavaScript 或SVG 或其他类型的纯文本文件。
我找到的解决方案是在通配符路由之前为service-worker.js
添加特定路由:
app.get("/service-worker.js", (req, res) => {
res.sendFile(path.resolve(__dirname, "public", "service-worker.js"));
});
app.get("*", function response(req, res) {
res.sendFile(path.join(__dirname, "public", "index.html"));
});
现在,当浏览器查找 service-worker.js
时,Express 会 return 使用正确的 MIME 类型。
(请注意,如果您尝试在通配符后添加 service-worker.js
路由,它不会起作用,因为通配符路由将被覆盖。)
ServiceWorker 支持的 MIME 类型是 'text/javascript'、application/javascript 和 application/x-javascript。转到您的服务器文件并设置
response.writeHead(201, {
'Content-Type': 'application/javascript'
});
该脚本具有不受支持的 MIME 类型 ('text/html')。 无法加载资源:net::ERR_INSECURE_RESPONSE (索引):1 未捕获(承诺)DOMException:无法注册 ServiceWorker:脚本具有不受支持的 MIME 类型('text/html')。
template.js 根文件
的代码export default ({ markup, css }) => {
return `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MERN Marketplace</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<style>
a{
text-decoration: none
}
</style>
<link rel="manifest" href="./manifest.json">
</head>
<body style="margin:0">
<div id="root">${markup}</div>
<style id="jss-server-side">${css}</style>
<script type="text/javascript" src="/dist/bundle.js"></script>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js').then(function() {
console.log("Service Worker Registered");
});
}
</script>
</body>
</html>`;
};
应用此更改:
'/service-worker.js' // ❌
'./service-worker.js' // ✅
解决了我的问题。
(在navigator.serviceWorker.register('/service-worker.js')
)
或者您可能需要:
'%PUBLIC_URL%/serviceworker.js'
感谢@DanielLord for
反应: public/index.html
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('sw-cached-site.js', function() {
navigator.serviceWorker.register('service-worker.js', {
scope: '/',
});
});
}
window.process = { env: { NODE_ENV: 'production' } };
</script>
注:满app/site public/sw-cached-site.js
const cacheName = 'v1';
self.addEventListener('activate', (e) =>{
e.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cache => {
if(cache !== cacheName) {
return caches.delete(cache);
}
})
)
})
)
});
self.addEventListener('fetch', e => {
e.respondWith(
fetch(e.request)
.then(res => {
const resClone = res.clone();
caches
.open(cacheName)
.then(cache => {
cache.put(e.request, resClone);
});
return res;
}).catch(err => caches.match(e.request).then(res => res))
);
});
确保已生成服务工作者文件(Chrome DevTools -> Sources -> Filesystem)。如果根本没有生成 service worker 文件(检查你的部署脚本),你可能会收到这样的错误。
如果您正在使用 NodeJS,serviceWorker 文件应放在 public 文件夹中。 如果您使用 Webpack 将 serviceWorker 导出到 public,则需要使用 'copy-webpack-plugin'.
我使用 nginx 为 React 应用程序提供服务,我解决了这个问题,将 mime 类型添加到 nginx:
http {
include mime.types; // <--- this line
# another config details
}
你还可以找到mime.types file here
我遇到了同样的问题,从我的配置中删除其他 firebase 库为我解决了这个问题 Check this on Github
// Change this
var firebaseConfig = {
apiKey: "*********",
authDomain: "**********",
databaseURL: "*********",
projectId: "***********",
storageBucket: "************",
messagingSenderId: "***********",
appId: "************"
};
// To =>
var firebaseConfig = {
apiKey: "*****************",
projectId: "**********",
messagingSenderId: "*******",
appId: "***********"
};
我认为 http://localhost:3000/service-worker.js
中不存在服务工作者文件,因此服务器返回 index.html。然后注册功能不知道如何处理 index.html 文件并告诉您 MIME 类型不正确。
一个快速修复方法是将 service-worker.js 文件复制到 public
文件夹,这样当您点击 http://localhost:3000/service-worker.js
时,您就可以在浏览器中看到该文件。
记得转到 ChromeDev > Applications > ServiceWorkers 并点击取消订阅。为了删除错误的。记住还要禁用缓存
就我而言,对于 Vue,我需要使用 command-line 工具在 public 目录中生成 mockServiceWorker.js,如下所述:
https://mswjs.io/docs/getting-started/integrate/browser
我从样本中不清楚这一点。具体到 运行 的 CLI 命令是:
npx msw init ./public
self.addEventListener('fetch', function(event) {});
在您的 service-worker.js 文件中添加以上代码
当 运行 webpack 开发服务器时,它会为缺少的资源呈现默认值 index.html。
如果您使用浏览器加载 http://localhost:3000/sw.js
,您实际上会看到一个呈现的 React 应用程序(由 index.html 启动)。这就是为什么 mime 类型是 html,而不是 javascript。
此回退到 index.html 旨在支持 SPA 和前端路由。例如 /product/123/reviews
在后端没有这样的 html 文件,JS SPA 应用程序在前端处理它。
为什么您的文件丢失了?我猜你在项目的根文件夹中创建了那个文件。
Webpack 开发服务器不从该根文件夹提供服务。
将您的 sw.js 移动到项目的 public/ 文件夹中,它将按预期提供。
我想,service worker 文件应该在根路径上。在我的例子中,我不能使用根路径,所以我使用 apache 重定向规则将 service-worker.js 重定向到我的子路径。
RewriteRule "^/service-worker.js$" "/sub/service-worker.js"
我在使用 python 托管网站时遇到了类似的问题。 None 这里的解决方案对我有用,我遇到了一个 bug posted in chrome dev forum,它设法解决了我的问题。显然,在我的案例中这是 windows 相关的问题,因为 .js 文件的注册表条目的内容类型设置为 text/plain 由于某些先前的配置,我不得不改回 application/javascript。
TLDR:
- 打开注册表编辑器
- 转到Computer\HKEY_CLASSES_ROOT\.js
- 将内容类型更改为 application/javascript
- 重新启动 Chrome 和 运行 您的网站
希望这对某些 none 以上作品有所帮助。
此错误是因为应用程序(在本例中为 Angular)未找到文件 service-worker.js
(ngsw-config.js
或其他名称文件)。
我通过添加 angular.json
:
"serviceWorker": true,
"ngswConfigPath": "service-worker.json",
这应该添加到所有配置:例如,生产、测试和暂存。