Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 1 Error with React, Babel and Webpack - express

I am building a CRUD web application using Webpack, Express, Epilogue, Sequelize, Sqlite3 and React. After setting up Webpack and Babel, I can add entries to the database but not retrieve entries. When I add an entry, if I look at http://localhost:3000/blogposts (one of my endpoints) the page is blank, but in the server output I see my entries get added.
server output in the console
To retrieve entries from the database I use:
getPosts = async () => {
const response = await fetch('/blogposts');
const data = await response.json();
data.forEach(item => item.editMode = false);
this.setState({ data })
}
And I get the error: Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 1
full error message
I assume this is an error with babel/webpack and await/async.
my webpack.config.js:
const path = require("path")
const HtmlWebPackPlugin = require("html-webpack-plugin")
module.exports = {
entry: {
main: './src/index.js'
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: '[name].js'
},
target: 'web',
devtool: 'source-map',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
},
]
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ['file-loader']
},
{
test: /\.json$/,
loader: 'json-loader'
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./src/index.html",
excludeChunks: [ 'server' ]
})
],
resolve: {
extensions: ["*",".js", ".jsx", "json"],
alias: {
'components': path.resolve(__dirname, '/components')
}
},
}
my webpackserver.config.js:
const path = require('path')
const nodeExternals = require('webpack-node-externals')
module.exports = {
entry: {
server: './src/server/server.js',
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: '[name].js'
},
target: 'node',
resolve: {
extensions: ['.js', '.jsx'],
alias: {
'components': path.resolve(__dirname, '/components')
}
},
node: {
__dirname: false,
__filename: false,
},
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
}
my server.js:
import path from 'path'
import express from 'express'
require('dotenv').config();
const cors = require('cors');
const bodyParser = require('body-parser');
const session = require('express-session');
const { ExpressOIDC } = require('#okta/oidc-middleware');
const Sequelize = require('sequelize');
const epilogue = require('epilogue'), ForbiddenError = epilogue.Errors.ForbiddenError;
const port = process.env.PORT || 3000
const app = express(),
DIST_DIR = __dirname,
HTML_FILE = path.join(DIST_DIR, '/src/index.html')
app.use(express.static(DIST_DIR))
app.get('*', (req, res) => {
res.sendFile(HTML_FILE)
})
// session support is required to use ExpressOIDC
app.use(session({
secret: process.env.RANDOM_SECRET_WORD,
resave: true,
saveUninitialized: false
}));
const oidc = new ExpressOIDC({
issuer: `${process.env.OKTA_ORG_URL}/oauth2/default`,
client_id: process.env.OKTA_CLIENT_ID,
client_secret: process.env.OKTA_CLIENT_SECRET,
redirect_uri: process.env.REDIRECT_URL,
scope: 'openid profile',
routes: {
callback: {
path: '/authorization-code/callback',
defaultRedirect: '/admin'
}
}
});
// ExpressOIDC will attach handlers for the /login and /authorization-code/callback routes
app.use(oidc.router);
app.use(cors());
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'src')));
app.get('/home', (req, res) => {
res.sendFile(path.join(__dirname, './home.html'));
});
app.get('/admin', oidc.ensureAuthenticated(), (req, res) => {
res.sendFile(path.join(__dirname, './admin.html'));
});
app.get('/logout', (req, res) => {
req.logout();
res.redirect('/home');
});
console.log("redirect");
app.get('/', (req, res) => {
res.redirect('/home');
});
// //for each blog post
app.get('/lifestyle/:title', function (req, res) {
res.send('Blogpost template here!')
})
const database = new Sequelize({
dialect: 'sqlite',
storage: './db.sqlite',
operatorsAliases: false,
});
const Post = database.define('posts', {
title: Sequelize.STRING,
content: Sequelize.TEXT,
});
const blogPost = database.define('blogposts', {
title: Sequelize.STRING,
content: Sequelize.TEXT,
published: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false,
},
});
const test = database.define('test', {
title: Sequelize.STRING,
content: Sequelize.TEXT,
});
epilogue.initialize({ app, sequelize: database });
const PostResource = epilogue.resource({
model: Post,
endpoints: ['/posts', '/posts/:id'],
});
const blogPostResource = epilogue.resource({
model: blogPost,
endpoints: ['/blogposts', '/blogposts/:id'],
});
PostResource.all.auth(function (req, res, context) {
return new Promise(function (resolve, reject) {
resolve(context.continue);
})
});
database.sync().then(() => {
oidc.on('ready', () => {
app.listen(port, () => console.log(`My Blog App listening on port ${port}!`))
});
});
oidc.on('error', err => {
// An error occurred while setting up OIDC
console.log("oidc error: ", err);
});
my package.json:
{
"name": "blog",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"build": "rm -rf dist && webpack --mode development --config webpackserver.config.js && webpack --mode development",
"start": "node ./dist/server.js"
},
"proxy": "http://localhost:3000",
"author": "",
"license": "ISC",
"dependencies": {
"#okta/oidc-middleware": "1.0.2",
"D": "1.0.0",
"babel-polyfill": "6.26.0",
"babel-preset-es2015": "6.24.1",
"babel-preset-stage-0": "6.24.1",
"babel-runtime": "6.26.0",
"body-parser": "1.18.3",
"cors": "2.8.5",
"dotenv": "6.2.0",
"epilogue": "0.7.1",
"express": "4.16.4",
"express-session": "1.15.6",
"fibers": "4.0.2",
"node-sass": "4.13.0",
"rc": "1.2.8",
"sass": "1.23.7",
"sequelize": "4.44.3",
"sqlite3": "4.1.0",
"webpack-isomorphic-tools": "3.0.6"
},
"devDependencies": {
"#babel/core": "7.7.5",
"#babel/plugin-proposal-class-properties": "7.7.4",
"#babel/plugin-transform-runtime": "7.7.6",
"#babel/preset-env": "7.7.6",
"#babel/preset-react": "7.7.4",
"#material-ui/core": "4.7.2",
"#material-ui/icons": "4.5.1",
"babel-loader": "8.0.6",
"babel-plugin-transform-runtime": "6.23.0",
"babel-preset-env": "1.7.0",
"css-loader": "3.3.2",
"file-loader": "5.0.2",
"grommet": "2.9.0",
"html-loader": "0.5.5",
"html-webpack-plugin": "3.2.0",
"json-loader": "0.5.7",
"nodemon": "1.18.9",
"nodemon-webpack-plugin": "4.2.2",
"react": "16.12.0",
"react-dom": "16.12.0",
"react-router-dom": "5.1.2",
"sass-loader": "8.0.0",
"style-loader": "1.0.1",
"styled-components": "4.4.1",
"typeface-roboto": "0.0.75",
"webpack": "4.41.2",
"webpack-cli": "3.3.10",
"webpack-node-externals": "1.7.2"
}
}
my .babelrc"
{
"presets": [
"#babel/preset-env",
"#babel/react"
],
"plugins" : [
"#babel/plugin-proposal-class-properties",
"#babel/plugin-transform-runtime"
]
}

Related

Mobx statechange not detected

I have a small simple setup. With mobx and preact.
class AppStore {
loadingobjects = true;
constructor() {
makeObservable(this, {
loadingobjects: observable,
});
this.fetchCommonObjects();
}
fetchCommonObjects = () => {
window
.fetch(url)
.then((res) => res.json())
.then((json) => {
/* data processing */
this.loadingobjects = false;
});
};
}
export const AppStoreContext = createContext();
function AppStoreProvider({ children }) {
return (
<AppStoreContext.Provider value={new AppStore()}>
{children}
</AppStoreContext.Provider>
);
}
export default AppStoreProvider;
export default function useAppStore() {
return useContext(AppStoreContext);
}
const List = observer(() => {
const store = useAppStore();
if (store.loadingobjects) {
return <div class="ui active centered inline loader"></div>;
} else {
return (page content);
}
});
problem is that store.loadingobjects Is always false. Seems like im doing something wrong but i cant put my finger on it...
What am i missing or doing wrong?
Edit addding my configs:
package.json
{
"name": "project",
"version": "0.0.2",
"license": "MIT",
"scripts": {
"start": "set NODE_ENV=dev && webpack serve --mode=development",
"build": "set NODE_ENV=production && webpack -p",
},
"devDependencies": {
"#babel/core": "^7.20.12",
"#babel/plugin-transform-runtime": "^7.19.6",
"#babel/preset-env": "^7.20.2",
"#babel/preset-react": "^7.18.6",
"babel-loader": "^9.1.2",
"babel-plugin-import": "^1.13.6",
"html-webpack-plugin": "^5.5.0",
"surge": "^0.19.0",
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.11.1"
},
"dependencies": {
"#babel/polyfill": "^7.12.1",
"mobx": "^6.7.0",
"mobx-react": "^7.6.0",
"preact": "^10.11.3"
}
}
webpack.config.js
const path = require('path');
const isProd = (process.env.NODE_ENV === 'production');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
//input
entry: ["#babel/polyfill",'./src'],
resolve: {
alias:{
"react": "preact/compat",
"react-dom": "preact/compat",
"react/jsx-runtime": "preact/jsx-runtime"
}
},
//output
output: {
path : path.join(__dirname, 'build'),
filename : 'bundle.js'
},
//transformations
module: {
rules : [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
}
]
},
//sourcemaps
devtool: 'source-map',
plugins: [new HtmlWebpackPlugin({
template: './src/index.html',
favicon: "./src/favicon.ico"
})],
//server
devServer: {
compress: true,
historyApiFallback: true
}
}
.babelrc
{
"presets": ["#babel/preset-react", ["#babel/preset-env", {"useBuiltIns": "usage",}]],
"plugins": [
["#babel/plugin-transform-runtime"],
[
"#babel/plugin-transform-react-jsx",
{
"pragma": "h",
"pragmaFrag": "Fragment"
}
]
]
}
I found the issue. I started cutting the components into smaller pieces and then adding and removing them into the component hierarchy until i found the component causing the issue. It turned out that i had done onClick={method()} and this was changeing state causing the endless rerenders.

Apollo=Express GraphQL error, cannot find module graphql

I am trying to set up a graphql express server with apollo, express, typeorm, and graphql, however I am getting this error now that I have implemented the UserResolver.ts file. I have already tried installing graphql and even have downgraded it to 14.2.1 but it still doesn't work. Here is the source code:
index.ts
import "reflect-metadata";
import express from 'express';
import {ApolloServer} from 'apollo-server-express';
import { buildSchema } from "type-graphql";
import { UserResolver } from "./UserResolver";
(async () => {
const app = express();
app.get('/', (_req, res) => res.send('hello'))
const apolloServer = new ApolloServer({
schema: await buildSchema({
resolvers: [UserResolver]
})
});
// my line idk if it works
await apolloServer.start();
apolloServer.applyMiddleware({ app });
app.listen(4000, () => {
console.log("express server started");
});
})()
// createConnection().then(async connection => {
// console.log("Inserting a new user into the database...");
// const user = new User();
// user.firstName = "Timber";
// user.lastName = "Saw";
// user.age = 25;
// await connection.manager.save(user);
// console.log("Saved a new user with id: " + user.id);
// console.log("Loading users from the database...");
// const users = await connection.manager.find(User);
// console.log("Loaded users: ", users);
// console.log("Here you can setup and run express/koa/any other framework.");
// }).catch(error => console.log(error));
UserResolver.ts
import { Query, Resolver } from 'type-graphql';
#Resolver()
export class UserResolver{
#Query(() => String)
hello(){
return "hi";
}
}
ormconfig.json
{
"type": "postgres",
"host": "localhost",
"port": 5432,
"username": "postgres",
"password": "7434006a",
"database": "graphqldatabase",
"synchronize": true,
"logging": false,
"entities": [
"src/entity/**/*.ts"
],
"migrations": [
"src/migration/**/*.ts"
],
"subscribers": [
"src/subscriber/**/*.ts"
],
"cli": {
"entitiesDir": "src/entity",
"migrationsDir": "src/migration",
"subscribersDir": "src/subscriber"
}
}
package.json
{
"name": "backend",
"version": "0.0.1",
"description": "Awesome project developed with TypeORM.",
"devDependencies": {
"#types/express": "^4.17.13",
"#types/graphql": "^14.5.0",
"#types/node": "^8.0.29",
"ts-node": "3.3.0",
"typescript": "3.3.3333"
},
"dependencies": {
"#nestjs/common": "^8.2.3",
"#nestjs/core": "^8.2.3",
"#nestjs/typeorm": "^8.0.2",
"apollo-server-express": "^3.5.0",
"express": "^4.17.1",
"graphql": "^14.2.1",
"pg": "^8.4.0",
"reflect-metadata": "^0.1.10",
"rxjs": "^7.4.0",
"typeorm": "0.2.41"
},
"scripts": {
"start": "ts-node src/index.ts",
"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js --config src/config/postgres.config.ts"
}
}

Nuxt, Vue, RefreshToken => Uncaught (in promise) TypeError: Cannot read property 'protocol' of undefined => Axios plugin, Axios Interceptors

my goal is to refresh the token after catching the 401 status code and the "token expired" message in my interceptor on the response ...
What are they doing wrong?
I'm using nuxt, vue, axios. Please help!
Uncaught (in promise) TypeError: Cannot read property 'protocol' of
undefined
it sends me back to that code:
#/plugins/axios.js:
import Vue from 'vue';
import axios from 'axios';
axios.interceptors.response.use((response) => {
console.debug("AXIOS.JS plugin => response: ", response);
return response;
}, function (error) {
console.debug("AXIOS.JS plugin => error: ", error);
return Promise.reject(error);
});
Vue.use(axios);
package.json:
{
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate"
},
"dependencies": {
"#nuxtjs/axios": "^5.13.1",
"#nuxtjs/composition-api": "^0.24.7",
"#nuxtjs/dotenv": "^1.4.1",
"#nuxtjs/proxy": "^2.1.0",
"#nuxtjs/pwa": "^3.3.5",
"#vue/composition-api": "^1.0.0-rc.13",
"core-js": "^3.9.1",
"nuxt": "^2.15.6",
"vue-multiselect": "^2.1.6",
"vue2-datepicker": "^3.9.1"
},
"devDependencies": {
"#nuxtjs/tailwindcss": "^4.1.2",
"autoprefixer": "^10.2.5",
"postcss": "^8.3.0",
"tailwindcss": "^2.1.2"
}
}
nuxt.config.js
const routes = require('./routes/index.js')
export default {
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'Fokser',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
],
script: [
{
//src: "https://skrypt-cookies.pl/id/d6458d5064c23515.js",
//src: "https://skrypt-cookies.pl/id/69205d8cab854dc2.js",
body: true,
},
],
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
'#/static/css/styles.css',
],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
{
src: "#/plugins/filters.js",
src: "#/plugins/axios.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: [
// https://go.nuxtjs.dev/tailwindcss
'#nuxtjs/tailwindcss',
'#nuxtjs/composition-api/module'
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
// https://go.nuxtjs.dev/axios
'#nuxtjs/axios',
// https://go.nuxtjs.dev/pwa
'#nuxtjs/pwa',
'#nuxtjs/proxy',
'#nuxtjs/dotenv'
],
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {
proxy: true
},
// PWA module configuration: https://go.nuxtjs.dev/pwa
pwa: {
manifest: {
lang: 'en'
}
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
},
proxy: {
'/api/': {
target: process.env.VUE_APP_ROOT_API,
pathRewrite: { '^/api': '' }
}
},
router: {
extendRoutes(nuxtRoutes, resolve) {
routes.forEach((route) => {
nuxtRoutes.push({
name: route.name,
path: route.path,
component: resolve(__dirname, route.component)
})
})
}
}
}
This occurs at main page (localhost):
besides, I am making a request to api like:
loadUserInfo({ commit }) {
let token = localStorage.getItem("auth_token");
let userId = localStorage.getItem("id");
commit("setUserToken", token);
commit("setUserId", userId);
if (userId && token) {
this.$axios.get(`api/accounts/userName/${userId}`)
.then((res) => {
if (res.status === 200) {
commit("setUserName", res.data.userName);
}
})
.catch(err => {
console.debug("[authorize.js LoadUserInfo], errors: ", err);
})
}
},
async getRecords({commit}, request) {
let config = {
params: {
recordType: request.recordType,
limit: limit
},
}
return await this.$axios.get(`/api/records/getRecords`, config);
}
loadAll({ commit }, request) {
this.$axios.get(`/api/records/all`, request)
.then((res) => {
if (res.status === 200) {
commit('setRecords', res.data);
}
});
},
I don't know where is the problem... :(

webpack: configuration.entry should be an non-empty object

serverless deploy is throwing this error with latest webpack verstion.
Serverless: Bundling with Webpack...
Webpack Options Validation Error -----------------------
WebpackOptionsValidationError: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.entry should be a non-empty object.
webpack.config.js
const path = require('path');
const slsw = require('serverless-webpack');
// var nodeExternals = require('webpack-node-externals')
module.exports = {
mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
entry: slsw.lib.entries,
// externals: [nodeExternals()],
devtool: 'source-map',
resolve: {
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
},
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, '.webpack'),
filename: '[name].js',
},
target: 'node',
module: {
rules: [
// all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
{ test: /\.tsx?$/, loader: 'ts-loader' },
],
},
};
package.json
"serverless": "^1.72.0",
"serverless-aws-documentation": "^1.1.0",
"serverless-dynamodb-local": "^0.2.39",
"serverless-iam-roles-per-function": "^2.0.2",
"serverless-offline": "^6.4.0",
"serverless-reqvalidator-plugin": "^1.0.3",
"serverless-s3-local": "^0.6.2",
"serverless-webpack": "^5.3.2",
"ts-loader": "^7.0.5",
"typescript": "^3.9.5",
"webpack": "^4.43.0"
there's something related here: https://github.com/serverless-heaven/serverless-webpack/issues/372
serverless.yml is very standard and was working with older webpack versions.
Not expert in webpack here, any help much appreciated.
The solution for this was to recreate the project with from the scratch and reinstall the packages:
sls create --template aws-nodejs-typescript --path projectname
in this case, the webpack.config.json generate looks like this:
const path = require('path');
const slsw = require('serverless-webpack');
const nodeExternals = require('webpack-node-externals');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
module.exports = {
context: __dirname,
mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
entry: slsw.lib.entries,
devtool: slsw.lib.webpack.isLocal ? 'cheap-module-eval-source-map' : 'source-map',
resolve: {
extensions: ['.mjs', '.json', '.ts'],
symlinks: false,
cacheWithContext: false,
},
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, '.webpack'),
filename: '[name].js',
},
target: 'node',
externals: [nodeExternals()],
module: {
rules: [
// all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
{
test: /\.(tsx?)$/,
loader: 'ts-loader',
exclude: [
[
path.resolve(__dirname, 'node_modules'),
path.resolve(__dirname, '.serverless'),
path.resolve(__dirname, '.webpack'),
],
],
options: {
transpileOnly: true,
experimentalWatchApi: true,
},
},
],
},
plugins: [
// new ForkTsCheckerWebpackPlugin({
// eslint: true,
// eslintOptions: {
// cache: true
// }
// })
],
};
and package.json:
"#types/aws-lambda": "^8.10.17",
"#types/node": "^10.12.18",
"fork-ts-checker-webpack-plugin": "^3.0.1",
"serverless": "^1.73.1",
"serverless-aws-documentation": "^1.1.0",
"serverless-dynamodb-local": "^0.2.39",
"serverless-iam-roles-per-function": "^2.0.2",
"serverless-offline": "^6.4.0",
"serverless-reqvalidator-plugin": "^1.0.3",
"serverless-s3-local": "^0.6.2",
"serverless-webpack": "^5.2.0",
"ts-loader": "^5.3.3",
"typescript": "^3.2.4",
"webpack": "^4.29.0",
"webpack-node-externals": "^1.7.2"
deployment both offline and cloud works ok.

.bind no longer working after upgrading to new Aurelia webpack plugins

I'm trying to update my Aurelia project that uses webpack so I can require .scss files in my templates. I've looked at the Aurelia Skeleton project for webpack and have followed this guide to come up with my webpack.config which is listed below. I have also included my package.json file.
I am able to load styles now, but have come across a perplexing issue. None of the my bind statements work anymore. The code itself didn't change and was working fine before this update attempt. I tried using two-way, one-way, etc, but that didn't work either. The #bindable property is always undefined.
<my-custom-element value.bind="something"></my-custom-element>
In MyCustomElement, value is always undefined although something is set properly.
I have tried walking back the package versions and I think it has to do with aurelia-bootstrapper, but I'm not sure.
I'm out of ideas on how to debug this issue. Any help would be much appreciated.
webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const DashboardPlugin = require('webpack-dashboard/plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const { AureliaPlugin, ModuleDependenciesPlugin } = require('aurelia-webpack-plugin');
const { optimize: { CommonsChunkPlugin }, ProvidePlugin } = require('webpack')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const project = require('./package.json');
// config helpers:
const ensureArray = (config) => config && (Array.isArray(config) ? config : [config]) || []
const when = (condition, config, negativeConfig) =>
condition ? ensureArray(config) : ensureArray(negativeConfig)
// primary config:
const title = 'Radar';
const outDir = path.resolve(__dirname, 'dist');
const srcDir = path.resolve(__dirname, 'src');
const nodeModulesDir = path.resolve(__dirname, 'node_modules');
const baseUrl = '/';
// If not done this way the plugin will try to load when only a build is required and cause it to hang.
const addDashboardPlugin = process.env.npm_lifecycle_event === 'webpack' ? [] : [new DashboardPlugin({
port: 3333
})];
const metadata = {
port: process.env.WEBPACK_PORT || 9000,
host: process.env.WEBPACK_HOST || 'localhost'
};
const cssRules = [
{ loader: 'css-loader' },
{
loader: 'postcss-loader',
options: { plugins: () => [require('autoprefixer')({ browsers: ['last 2 versions'] })] }
}
]
module.exports = ({ production, server, extractCss, coverage } = {}) => ({
resolve: {
extensions: ['.js'],
modules: [srcDir, 'node_modules'],
},
entry: {
app: ['aurelia-bootstrapper'],
aurelia: Object.keys(project.dependencies).filter(dep => dep.startsWith('aurelia-')),
vendor: Object.keys(project.dependencies).filter(dep => !dep.startsWith('aurelia-'))
},
devtool: production ? 'source-map' : 'inline-source-map',
output: {
path: outDir,
publicPath: baseUrl,
filename: production ? '[name].[chunkhash].bundle.js' : '[name].[hash].bundle.js',
sourceMapFilename: production ? '[name].[chunkhash].bundle.map' : '[name].[hash].bundle.map',
chunkFilename: production ? '[name].[chunkhash].chunk.js' : '[name].[hash].chunk.js',
},
devServer: {
contentBase: outDir,
// serve index.html for all 404 (required for push-state)
historyApiFallback: true,
port: metadata.port,
host: metadata.host,
watchOptions: {
aggregateTimeout: 300,
poll: 1000
}
},
module: {
rules: [
{
test: /\.scss$/i,
issuer: [{ not: [{ test: /\.html$/i }] }],
loaders: ['style-loader', 'css-loader?sourceMap', 'sass-loader?sourceMap']
},
{
test: /\.scss$/i,
issuer: [{ test: /\.html$/i }],
loaders: ['css-loader?sourceMap', 'sass-loader?sourceMap']
},
// CSS required in JS/TS files should use the style-loader that auto-injects it into the website
// only when the issuer is a .js/.ts file, so the loaders are not applied inside html templates
{
test: /\.css$/i,
issuer: [{ not: [{ test: /\.html$/i }] }],
use: extractCss ? ExtractTextPlugin.extract({
fallback: 'style-loader',
use: cssRules,
}) : ['style-loader', ...cssRules],
},
{
test: /\.css$/i,
issuer: [{ test: /\.html$/i }],
// CSS required in templates cannot be extracted safely
// because Aurelia would try to require it again in runtime
use: cssRules,
},
{ test: /\.html$/i, loader: 'html-loader' },
{
test: /\.js$/i, loader: 'babel-loader', exclude: nodeModulesDir,
options: coverage ? { sourceMap: 'inline', plugins: ['istanbul'] } : {},
},
{ test: /\.json$/i, loader: 'json-loader' },
// use Bluebird as the global Promise implementation:
{ test: /[\/\\]node_modules[\/\\]bluebird[\/\\].+\.js$/, loader: 'expose-loader?Promise' },
// embed small images and fonts as Data Urls and larger ones as files:
{ test: /\.(png|gif|jpg|cur)$/i, loader: 'url-loader', options: { limit: 8192 } },
{ test: /\.woff2(\?v=[0-9]\.[0-9]\.[0-9])?$/i, loader: 'url-loader', options: { limit: 10000, mimetype: 'application/font-woff2' } },
{ test: /\.woff(\?v=[0-9]\.[0-9]\.[0-9])?$/i, loader: 'url-loader', options: { limit: 10000, mimetype: 'application/font-woff' } },
// load these fonts normally, as files:
{ test: /\.(ttf|eot|svg|otf)(\?v=[0-9]\.[0-9]\.[0-9])?$/i, loader: 'file-loader' },
]
},
plugins: [
new AureliaPlugin(),
new ModuleDependenciesPlugin({
'aurelia-dialog': ['./ai-dialog', './ai-dialog-header', './ai-dialog-footer', './ai-dialog-body',
'./attach-focus', './dialog-configuration', './dialog-controller', './dialog-options', './dialog-renderer',
'./dialog-result', './dialog-service', './lifecycle', './renderer'],
'aurelia-chart': ['./elements/chart-element', './attributes/chart-attribute', './observers/model-observer']
}),
new ProvidePlugin({
'Promise': 'bluebird'
}),
new HtmlWebpackPlugin({
template: 'index.ejs',
minify: production ? {
removeComments: true,
collapseWhitespace: true
} : undefined,
metadata: {
title, server, baseUrl
},
}),
new CopyWebpackPlugin([
{ from: 'src/config', to: 'config' },
{ from: 'styles/img', to: 'img' }
]),
...when(extractCss, new ExtractTextPlugin({
filename: production ? '[contenthash].css' : '[id].css',
allChunks: true,
})),
...when(production, new CommonsChunkPlugin({
name: 'common'
})),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.scss$/i,
cssProcessor: require('cssnano'),
cssProcessorOptions: { discardComments: { removeAll: true } },
canPrint: true
})
].concat(addDashboardPlugin)
})
package.json
"dependencies": {
"aurelia-animator-css": "^1.0.0",
"aurelia-application-insights": "^1.0.0",
"aurelia-binding": "^1.2.0",
"aurelia-bootstrapper": "^2.1.1",
"aurelia-chart": "^0.2.6",
"aurelia-configuration": "1.0.17",
"aurelia-dependency-injection": "^1.3.1",
"aurelia-dialog": "^1.0.0-beta.3.0.0",
"aurelia-event-aggregator": "^1.0.1",
"aurelia-fetch-client": "^1.1.2",
"aurelia-framework": "^1.1.0",
"aurelia-history": "^1.0.0",
"aurelia-history-browser": "^1.0.0",
"aurelia-logging": "^1.3.1",
"aurelia-logging-console": "^1.0.0",
"aurelia-metadata": "^1.0.3",
"aurelia-notify": "^0.8.1",
"aurelia-pal": "^1.3.0",
"aurelia-pal-browser": "^1.1.0",
"aurelia-path": "^1.0.0",
"aurelia-route-recognizer": "^1.0.0",
"aurelia-router": "^1.3.0",
"aurelia-task-queue": "^1.2.0",
"aurelia-templating": "^1.3.0",
"aurelia-templating-binding": "^1.3.0",
"aurelia-templating-resources": "^1.3.1",
"aurelia-templating-router": "^1.1.0",
"aurelia-validation": "^1.0.0",
"bluebird": "^3.3.5",
"json-loader": "^0.5.4",
... //omitted for clarity
},
"devDependencies": {
"aurelia-loader-nodejs": "^1.0.1",
"aurelia-pal-nodejs": "^1.0.0-beta.1.0.0",
"aurelia-tools": "^1.0.0",
"aurelia-webpack-plugin": "^2.0.0-rc.2",
"autoprefixer": "^7.0.0",
"babel-core": "^6.17.0",
"babel-eslint": "^7.2.3",
"babel-loader": "^7.0.0",
"babel-plugin-istanbul": "^4.1.3",
"babel-plugin-lodash": "^3.2.10",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-polyfill": "^6.16.0",
"babel-preset-env": "^1.5.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-stage-1": "^6.24.1",
"babel-register": "^6.11.6",
"concurrently": "^2.2.0",
"copy-webpack-plugin": "^4.0.1",
"cross-env": "^3.1.3",
"css-loader": "^0.28.1",
"eslint": "^3.12.2",
"extract-text-webpack-plugin": "^2.1.0",
"file-loader": "^0.9.0",
"html-server": "^0.1.1",
"html-webpack-plugin": "^2.22.0",
"json-loader": "^0.5.4",
"node-sass": "^3.13.0",
"optimize-css-assets-webpack-plugin": "^1.3.2",
"package": "^1.0.1",
"postcss-loader": "^1.3.3",
"raw-loader": "^0.5.1",
"rimraf": "^2.5.2",
"sass-loader": "^4.0.2",
"style-loader": "^0.17.0",
"url-loader": "^0.5.8",
"webpack": "^2.6.1",
"webpack-dashboard": "^0.2.0",
"webpack-dev-server": "^2.4.5"
}
nav-bar.html
<template>
<require from='./_nav-bar.scss'></require>
<section class="nav-bar nav-bar__group" data-grid="full">
<div data-grid="full">
<main-menu router.bind="router" data-grid="21"></main-menu>
<user-panel data-grid="3"></user-panel>
</div>
</section>
</template>
main-menu.html
<template class="main-menu">
<ul class="main-menu__nav-list">
<li repeat.for="row of router.navigation">
<a href.bind="row.href"
data-appinsights-category="navigation"
data-appinsights-action="${row.title}"
data-text="${row.title}">
${row.title}
</a>
</li>
</ul>
</template>
main-menu.js
import { bindable, inject } from 'aurelia-framework';
#inject(Element)
export class MainMenuCustomElement {
//This value is always undefined now
#bindable router;
constructor(element) {
this.element = element;
}
toggleMenu() {
//removed for brevity
}
}
I got it to work after adding import babel-polyfill to main.js, changing .babelrc to reference `.babelrc.js like so:
{
"presets": [ "./.babelrc.js" ]
}
I also included .babelrc.js from the skeleton-navigation project.
.babelrc.js
// this file will be used by default by babel#7 once it is released
module.exports = {
"plugins": [
"transform-decorators-legacy",
"transform-class-properties"
],
"presets": [
[
"env", {
"targets": process.env.BABEL_TARGET === 'node' ? {
"node": process.env.IN_PROTRACTOR ? '6' : 'current'
} : {
"browsers": [
"last 2 versions",
"not ie <= 11"
],
"uglify": process.env.NODE_ENV === 'production',
},
"loose": true,
"modules": process.env.BABEL_TARGET === 'node' ? 'commonjs' : false,
"useBuiltIns": true
}
]
]
}