javascript Webpack 开发服务器抛出错误 - 拒绝执行脚本,因为其 MIME 类型('text/html')不可执行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47996128/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Webpack dev server throws error - Refused to execute script because its MIME type ('text/html') is not executable
提问by Matt
I use Webpack bundler and Webpack dev server for local development. The front-end is in React.js+Redux and the back-end in Node.js and koajs.
我使用 Webpack bundler 和 Webpack dev server 进行本地开发。前端使用 React.js+Redux,后端使用 Node.js 和 koajs。
In back-end, I use passportjslibrary for user authentication and other libraries koa-passport, passport-facebook, passport-google-authfor authentication through Facebook or Google. Basically, I implemented koa-passport-example.
在后端,我使用passportjs库进行用户身份验证,并使用其他库koa-passport、passport-facebook、passport-google-auth通过Facebook 或Google 进行身份验证。基本上,我实现了koa-passport-example。
If my application wants to redirect user to Facebook or Google login page, Webpack dev server throws error:
如果我的应用程序想要将用户重定向到 Facebook 或 Google 登录页面,Webpack 开发服务器会抛出错误:
GET http://localhost:8090/auth/bundle.js net::ERR_ABORTED
Refused to execute script from 'http://localhost:8090/auth/bundle.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
If I generate bundle by Webpack and host it on Node.js server, I don't get this error. I need to find out how to set up Webpack dev server to get rid of this error message.
如果我通过 Webpack 生成包并将其托管在 Node.js 服务器上,则不会出现此错误。我需要找出如何设置 Webpack 开发服务器来消除此错误消息。
package.json
包.json
"scripts": {
"debug": "./node_modules/nodemon/bin/nodemon.js --inspect ./script/server.js",
"webpack": "npm run serve | npm run dev",
"start": "node ./script/server.js",
"serve": "./node_modules/.bin/http-server -p 8080",
"dev": "webpack-dev-server -d --progress --colors --port 8090 --hot --inline",
},
"dependencies": {
"@koa/cors": "^2.2.1",
"actions": "^1.3.0",
"aws-s3-form": "^0.3.5",
"aws-sdk": "^2.165.0",
"axios": "^0.16.2",
"bootstrap": "^3.3.7",
"bootstrap-timepicker": "github:janzenz/bootstrap-timepicker#feature/compatibility-es6",
"d3-ease": "^1.0.3",
"d3-selection": "^1.1.0",
"d3-shape": "^1.2.0",
"d3-transition": "^1.1.0",
"font-awesome": "^4.7.0",
"http-server": "^0.10.0",
"immutable": "^3.8.2",
"jquery": "^3.2.1",
"jquery-ui": "^1.12.1",
"jquery.panzoom": "^3.2.2",
"jsonwebtoken": "^8.1.0",
"juration": "^0.1.0",
"knex": "^0.14.2",
"koa": "^2.3.0",
"koa-body": "^2.5.0",
"koa-bodyparser": "^4.2.0",
"koa-logger": "^3.1.0",
"koa-passport": "^4.0.1",
"koa-ratelimit": "^4.0.0",
"koa-router": "^7.2.1",
"koa-send": "^4.1.1",
"koa-session": "^5.5.1",
"koa-static": "^4.0.2",
"moment": "^2.18.1",
"objection": "^0.9.2",
"oembed-auto": "0.0.3",
"passport": "^0.4.0",
"passport-facebook": "^2.1.1",
"passport-google-oauth": "^1.0.0",
"passport-jwt": "^3.0.1",
"pg": "^7.4.0",
"probe-image-size": "^3.1.0",
"puppeteer": "^0.12.0",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-dropzone": "^4.2.1",
"react-facebook-login": "^3.6.2",
"react-google-login": "^3.0.2",
"react-modal": "^3.1.2",
"react-redux": "^5.0.6",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-router-redux": "^4.0.8",
"react-share": "^1.17.0",
"react-transition-group": "^1.2.1",
"react-twitter-widgets": "^1.7.1",
"redux": "^3.7.2",
"redux-thunk": "^2.2.0",
"request": "^2.83.0",
"request-promise-native": "^1.0.5",
"select2": "^4.0.4",
"select2-bootstrap-theme": "0.1.0-beta.10",
"shave": "^2.1.3",
"sqlite3": "^3.1.13",
"sugar-date": "^2.0.4",
"svg-url-loader": "^2.3.0",
"twitter": "^1.7.1",
"twitter-widgets": "^1.0.0",
"unfluff": "^1.1.0"
},
"devDependencies": {
"autoprefixer": "^7.1.4",
"babel": "^6.23.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"css-loader": "^0.28.7",
"duplicate-package-checker-webpack-plugin": "^2.0.2",
"eslint": "^4.7.2",
"eslint-config-airbnb": "^15.1.0",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-jsx-a11y": "^5.1.1",
"eslint-plugin-react": "^7.4.0",
"favicons-webpack-plugin": "0.0.7",
"file-loader": "^0.11.2",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"less": "^2.7.2",
"less-loader": "^4.0.5",
"node-sass": "^4.5.3",
"nodemon": "^1.12.1",
"npm-install-webpack-plugin": "^4.0.5",
"postcss": "^6.0.11",
"postcss-loader": "^2.0.6",
"sass-loader": "^6.0.6",
"style-loader": "^0.18.2",
"url-loader": "^0.5.9",
"webpack": "^3.6.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0",
"webpack-notifier": "^1.5.0"
}
webpack.config.js
webpack.config.js
const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const path = require('path');
const WebpackNotifierPlugin = require('webpack-notifier');
const autoprefixer = require('autoprefixer');
const TARGET = process.env.npm_lifecycle_event;
console.log(`target event is ${TARGET}`);
let outputFileName = 'app';
outputFileName += TARGET === 'prod' ? '.min.js' : '.js';
const common = {
entry: {
app: './index.jsx',
},
module: {
rules: [
{
test: /\.js[x]?$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader?presets[]=es2015&presets[]=react',
},
},
{
test: /\.scss$/,
loaders: [
'style-loader',
'css-loader',
'sass-loader',
],
},
{
test: /\.less$/,
loaders: ['style-loader', 'css-loader', 'less-loader'],
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(eot|ttf|svg|gif|png|jpg|otf|woff|woff2)$/,
loader: 'url-loader',
},
],
},
plugins: [
new webpack.ProvidePlugin({
jQuery: 'jquery',
$: 'jquery',
jquery: 'jquery',
'window.jQuery': 'jquery',
}),
new webpack.LoaderOptionsPlugin({
options: {
postcss: [
autoprefixer({
browsers: ['last 3 versions'],
}),
],
},
}),
new WebpackNotifierPlugin(),
],
};
if (TARGET === 'dev' || !TARGET) {
module.exports = webpackMerge(common, {
devtool: 'eval-source-map',
output: {
filename: 'bundle.js',
sourceMapFilename: '[file].map',
},
devServer: {
contentBase: path.resolve(__dirname), // New
historyApiFallback: true,
},
});
}
login.jsx
登录.jsx
...
<a href="/auth/facebook" className="btn btn--secondary ut-font-decima">Login</a>
...
server.js
服务器.js
const Koa = require('koa');
const Router = require('koa-router');
const logger = require('koa-logger');
const cors = require('@koa/cors');
const bodyParser = require('koa-bodyparser');
const serve = require('koa-static');
const path = require('path');
const session = require('koa-session');
const app = new Koa();
// trust proxy
app.proxy = true;
const router = new Router();
// sessions
app.keys = ['your-session-secret'];
app.use(session({}, app));
app.use(logger());
app.use(cors());
app.use(bodyParser());
require('./controllers/auth');
const passport = require('koa-passport');
app.use(passport.initialize());
app.use(passport.session());
app.use(serve(path.join(process.env.PWD, '/dist')));
router
.get('/auth/facebook', passport.authenticate('facebook'))
.get(
'/auth/facebook/callback',
passport.authenticate('facebook', {
successRedirect: '/podcast',
failureRedirect: '/',
}),
);
app.use(router.routes()).use(router.allowedMethods());
// don't listen to this port if the app is required from a test script
if (!module.parent) {
app.listen(process.env.PORT || 1337);
console.log('app listen on port: 1337');
}
回答by RickyM
Looking into Webpack further we should be clear about what Webpack is and what it is used for. Webpack is front end tool, it will build front end projects and has the capability of managing tasks similar to gulp/grunt. It can be a server to serve static content. But what it is not is a full fledged back end server. You can't easily build back end API and manage complex routing. This includes things like login functionality. Instead of reinventing the wheel, use Webpack as a dev tool to easily modify and see the updated result for web design. And if you need more functionality integrate Webpack by running it in watch mode and run the back end server at the same time and setup a proxy so that Webpack will defer to the back end server for complex routing. You can use any back end technology, though Webpack is built on Common.js library so integrating it into node.js and express seems to be the easiest because they are part of a javascript ecosystem.
进一步研究 Webpack,我们应该清楚 Webpack 是什么以及它的用途。Webpack 是前端工具,它将构建前端项目,并具有类似于 gulp/grunt 的管理任务的能力。它可以是提供静态内容的服务器。但它不是一个成熟的后端服务器。您无法轻松构建后端 API 并管理复杂的路由。这包括登录功能等。与其重新发明轮子,不如使用 Webpack 作为开发工具来轻松修改和查看网页设计的更新结果。如果您需要更多功能,可以通过在监视模式下运行 Webpack 并同时运行后端服务器并设置代理来集成 Webpack,以便 Webpack 将服从后端服务器进行复杂路由。您可以使用任何后端技术,尽管 Webpack 是基于 Common 构建的。
If I could comment I would, anyhow, I was reading through the webpack docs for the DevServer and I Think that the server is responding with the incorrect MIME type possibly because it isn't finding the bundle.js script where it is expecting it. I noticed the console output being 'http://localhost:8090/auth/bundle.js' and in the documentation the dev server expects it in the root. I think that if bundle.js is really in the auth directory that you may need to tell the server where it is with the publicPath option.
如果我可以发表评论,无论如何,我正在阅读 DevServer 的 webpack 文档,我认为服务器正在以不正确的 MIME 类型进行响应,可能是因为它没有在期望的地方找到 bundle.js 脚本。我注意到控制台输出是“ http://localhost:8090/auth/bundle.js”,并且在文档中开发服务器期望它在根目录中。我认为如果 bundle.js 真的在 auth 目录中,你可能需要用 publicPath 选项告诉服务器它在哪里。
output: {
filename: 'bundle.js',
sourceMapFilename: '[file].map',
path: path.resolve('build/js/),// moves the bundle.js out of the root
publicPath: '/auth/' // it is recommended that the publicPath is declared in both output and devServer
// publicPath links the path of bundle.js to this path in the html.
},
devServer: {
contentBase: path.resolve(__dirname), // New
historyApiFallback: true,
publicPath: "/auth/" // Both publicPath options should be the same as what is in your html loading the scripts
},
As I understand the webpack dev server, the bundle.js is not written to disc. It is served virtually.
据我了解 webpack 开发服务器,bundle.js 没有写入光盘。它以虚拟方式提供。
Now with all of this there is a need to either proxy the already built node.js server or build one to handle just the api you need to use. Webpack provides a dev middleware module to use as middleware in a basic node.js express server. You can see the basics of the middleware here. What you really need to start with from the documentation is installing via npm webpack-dev-middleware and express
现在有了所有这些,需要代理已经构建的 node.js 服务器或构建一个只处理您需要使用的 api。Webpack 提供了一个 dev 中间件模块,用作基本 node.js express 服务器中的中间件。您可以在此处查看中间件的基础知识。您真正需要从文档开始的是通过 npm webpack-dev-middleware 和 express 安装
npm install --save-dev webpack-dev-middleware express
npm install --save-dev webpack-dev-middleware express
Then create a new server file like index.js in the root of the project because you already have a server.js. Now create the basic server that you need with only the routing and packages you need to handle the api calls.
然后在项目的根目录中创建一个新的服务器文件,如 index.js,因为您已经有了 server.js。现在创建您需要的基本服务器,仅包含处理 api 调用所需的路由和包。
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);
// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath
}));
// Serve the files on port 3000.
app.listen(3000, function () {
console.log('Example app listening on port 3000!\n');
});
This is from the webpack website and you will need to do your own api routing. And you would run the project like a normal node project and it should handle the bundle.js requests.
这是来自 webpack 网站,你需要做你自己的 api 路由。您可以像普通节点项目一样运行该项目,它应该处理 bundle.js 请求。
And let's not forget that there is a plubin for koa koa-webpack-dev.I haven't personally used koa, but if you need it you can see how to use it here.
别忘了还有一个 koa 插件koa-webpack-dev。我个人没有使用过 koa,但如果你需要它,你可以在这里查看如何使用它。
回答by Ryan DuShane
i had a similar issue and thought i'd post my solution incase anyone had a similar issue. basically, i was trying to refresh my app on a dynamic subroute, localhost:3000/route/dynamicRoute, and it was throwing a similar error. i solved my issue by adding publicPath: '/'to my outputsettings in my webpack config. the following is my webpack.config.jsfor reference.
我有一个类似的问题,并认为我会发布我的解决方案,以防万一有人遇到类似的问题。基本上,我试图在动态子路由上刷新我的应用程序localhost:3000/route/dynamicRoute,但它抛出了类似的错误。我通过添加publicPath: '/'到output我的 webpack 配置中的设置解决了我的问题。以下是我的webpack.config.js供参考。
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const outputDirectory = 'dist';
module.exports = {
entry: ['babel-polyfill', './src/client/index.js'],
output: {
path: path.join(__dirname, outputDirectory),
filename: 'bundle.js',
publicPath: '/'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(pdf|jpg|png|gif|svg|ico)$/,
use: [
{
loader: 'url-loader'
},
]
}
]
},
devServer: {
port: 3000,
open: true,
proxy: {
'/api': 'http://localhost:8080'
},
historyApiFallback: true,
contentBase: './public/index.html',
hot: true
},
plugins: [
new CleanWebpackPlugin([outputDirectory]),
new HtmlWebpackPlugin({
template: './public/index.html',
favicon: './public/favicon.ico'
})
]
};

