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.
In back-end, I use passportjs library for user authentication and other libraries koa-passport, passport-facebook, passport-google-auth for authentication through Facebook or Google. Basically, I implemented koa-passport-example.
If my application wants to redirect user to Facebook or Google login page, Webpack dev server throws error:
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.
package.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
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
...
<a href=/auth/facebook className=btn btn--secondary ut-font-decima>Login</a>
...
server.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');
}