I am having the issue with trying to use .ejs files with Webpack. I have tried numerous packages and haven't managed to figure it out. I have five files that I want to render and have a layout.ejs which acts as a base for my application. I am using ejs-loader as it is the most popular. When I run webpack, I get the following error:
ERROR in Template execution failed: ReferenceError: body is not defined
I am relatively new to module bundling and have tried to follow the docs as close as possible.
webpack.config.js
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const nodeExternals = require('webpack-node-externals')
const config = {
target: 'node',
mode: 'development',
entry: './app.js',
externals: [nodeExternals()],
output: {
path: path.join(__dirname, './dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
{
test: /\.ejs$/,
loader: 'ejs-loader?variable=data'
},
]
},
plugins: [
new HtmlWebpackPlugin({
template: './views/layout.ejs',
hash: true,
}),
new webpack.ProvidePlugin({
_: "underscore"
})
]
}
module.exports = config;
layout.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/"
crossorigin="anonymous">
<link rel="stylesheet" href="https://bootswatch.com/4/flatly/bootstrap.min.css" />
<title>MyApp</title>
</head>
<body>
<div class="container">
<%- body %>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k"
crossorigin="anonymous"></script>
<script src="../dist/bundle.js"></script>
</body>
</html>
Related
I'm pretty new to react and webpack, and I'm trying to use react-router-dom for routing in my web app.
But something weird happens, when I defined the path for my component to '/:guid' everything works fine, but if I set it to '/users/:guid' I'm getting a blank page when I refresh the page.
I read some posts that said to add 'publicPath' and 'historyApiFallback: true' to my webpack.config.js but it still doesn't work for some reason. although, before adding it, I got 'cannot GET url' error.
Router.js:
import React from 'react';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import UserInfo from '../Containers/UserInfo/UserInfo';
import Main from './Main/Main';
const Router = () => {
return (
<BrowserRouter>
<Switch>
<Route exact path='/' component={Main} />
<Route path='/users/:guid' component={UserInfo} />
</Switch>
</BrowserRouter>
);
};
export default Router;
webpack.config.js:
const path = require('path');
const DIST_DIR = path.resolve(__dirname, 'dist');
const SRC_DIR = path.resolve(__dirname, 'src');
const config = {
entry: `${SRC_DIR}/app/index.js`,
output: {
path: `${DIST_DIR}/`,
filename: 'bundle.js',
publicPath: '/'
},
module: {
rules: [
{
test: /\.js?$/,
include: SRC_DIR,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-2']
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
devServer: {
historyApiFallback: true
}
};
module.exports = config;
Well, after some more research, I got to this github webpack-dev-server issue page that suggests to add a <base /> to my "index.html" file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React Training Project</title>
<base href="/">
</head>
<body>
<div id="app"></div>
<script src="./bundle.js"></script>
</body>
</html>
Apparently this is what I was missing.
This worked for me, thank you
<base href="/">
I have a completed project done on my local machine and am currently learning how to deploy it to production. I figured out a lot of things in the documentation for production and such but I have been stuck for awhile now on the part on how to tell my server to serve my static assets that contain my build files that I executed with web pack. For the record, I'm not using create-react-app I'm using the webpack-dev-server cli.
I've only ever connected to my server successfully and ran routes through it using MySQL but I never tested serving the static files on the server when my development was ready for production. I'm getting an error in the console when I try to serve my static build files. I can't tell if the error is because I have my routes being served wrong on my server or there is an issue in my index.html build.
Here is my code the server file is big so I'll only show the relevant parts pertaining to the issue I'm stuck on:
Server file:
const express = require("express");
const bodyParser = require("body-parser");
const path = require("path");
const cors = require("cors");
const router = express.Router();
const app = express();
const port = 5000;
app.use(cors());
// Body Parser Middleware
app.use(bodyParser.json({ limit: "50mb" }));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
app.get("*", function(request, response) {
response.sendFile(path.join(__dirname + "/../public/index.html"));
});
// Serve static files on server
app.use("../", express.static(__dirname + "public/index.html"));
app.listen(port, () => {
console.log(`Server started on port ${port}`);
});
Build Index.html File
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#000000">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<link href='https://fonts.googleapis.com/css?family=PT+Sans:400,400italic,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/v4-shims.css">
<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css" rel="stylesheet">
<link rel="stylesheet" href="/public/assets/css/pignose.calendar.min.css">
<link href="/public/assets/css/styles.css" rel="stylesheet" type="text/css">
<title></title>
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="/public/assets/js/jquery-3.3.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
<!-- Ck Editor Library -->
<script src="/public/assets/js/plugins/ckeditor/ckeditor.js"></script>
<!-- Pignose Calendar -->
<script src="/public/assets/js/pignose.calendar.full.min.js"></script>
<script type="text/javascript" src="/public/assets/js/scripts.js"></script>
</body>
</html>
Webpack Production
const webpack = require("webpack");
const path = require("path");
const CompressionPlugin = require("compression-webpack-plugin");
const nodeExternals = require("webpack-node-externals");
const HtmlWebPackPlugin = require("html-webpack-plugin");
var browserConfig = {
entry: ["babel-polyfill", __dirname + "/src/index.js"],
output: {
path: path.resolve(__dirname + "/build"),
filename: "bundle.js",
publicPath: "/"
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
query: {
presets: ["react", "env", "stage-0"]
}
}
},
{
test: /\.css$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" },
{ loader: "sass-loader" }
]
}
]
},
plugins: [
new CompressionPlugin({
filename: "[path].gz[query]",
algorithm: "gzip",
minRatio: 0.8,
threshold: 8192
}),
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("production")
}),
new HtmlWebPackPlugin({
template: "./public/index.html"
})
]
};
var serverConfig = {
target: "node",
externals: [nodeExternals()],
entry: __dirname + "/server/main.js",
output: {
path: path.resolve(__dirname + "/build"),
filename: "bundle.js",
publicPath: "/"
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
query: {
presets: ["react", "env", "stage-0"]
}
}
}
]
}
};
module.exports = [browserConfig, serverConfig];
Folder Architecture
Error log I'm getting when I try to connect to my port for my build files:
second error:
In express middleware configurations order matters, since app.get("*", function(request, response) is in the top every request will go through that and send the index.html. Change the order like this
// Serve static files on server
app.use('/public', express.static(__dirname + "/../public"));
app.get("*", function (request, response) {
response.sendFile(path.join(__dirname + "/../public/index.html"));
});
and it should work
Edit
As your request to extend my answer, what was happening here is since you haven't configured the public direcotry, express server will get to the next request handler which is app.get("*" , ... which sends the index.html as the response. So when you request this javascript file
<script type="text/javascript" src="/public/assets/js/jquery-3.3.1.min.js"></script>
It will send the index.html as i mentioned without sending the jquery-3.3.1.min.js and same for every js and css files, but your browser is expecting a javascript file and try to parse it so the file <!doctype> .. is parsing and since it is not a valid javascript, it prints the error. Hope that helps
I'm trying to serve my react app from an express server with a catch all route so that users can still access react routes when they refresh the page or manually type in a url. However, when I try to serve the app entry point, /dist/index.html, from my express server I get Uncaught SyntaxError: Unexpected token <
When I look at the main.js file in the sources tab of the console, this is what is see:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React E-Store</title>
</head>
<body>
<div id="root">
</div>
</body>
<script src="/dist/main.js"></script>
</html>
This is what my server.js file looks like:
const express = require('express')
const path = require('path')
const port = process.env.PORT || 8080
const app = express()
// Handles all routes so you do not get a not found error
app.get('/*', function (request, response){
response.sendFile(path.resolve(__dirname, "dist", "index.html"))
})
app.listen(port)
console.log("server started on port " + port)
and here is my webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
template: './index.html',
filename: 'index.html',
inject: 'body'
})
module.exports = {
entry: './src/app.js',
output: {
path: path.resolve('dist'),
publicPath: '/dist/',
filename: '[name].js'
},
module: {
loaders: [
{ test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
{ test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/ },
{
test: /\.(png|jp(e*)g|svg)$/,
loader: 'url-loader',
options: {
limit: 8000, // Convert images < 8kb to base64 strings
name: 'images/[hash]-[name].[ext]'
}
},
{
test: /\.sass$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}]}
]
},
plugins: [HtmlWebpackPluginConfig]
}
I appreciate any help
So i have an Angular 2 app that runs locally without problems. When deploying my app using heroku i get following errors:
>SyntaxError: expected expression, got '<'
><!DOCTYPE html>
>shim.min.js (Zeile 1)
>
>SyntaxError: expected expression, got '<'
><!DOCTYPE html>
>zone.js (Zeile 1)
>
>SyntaxError: expected expression, got '<'
><!DOCTYPE html>
>Reflect.js (Zeile 1)
>
>SyntaxError: expected expression, got '<'
><!DOCTYPE html>
>system.src.js (Zeile 1)
>
>ReferenceError: System is not defined
>systemj...nfig.js (Zeile 6, Spalte 3)
>
>ReferenceError: System is not defined
>mean1nv...app.com (Zeile 24, Spalte 7)
There are similar posts that suggest all kind of changes but i dont know where it breaks in my code. I feel kind of blind, i deployed a similar app before without problems and I cant find the difference.
server.js
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var items = require('./routes/items');
var app = express();
app.set('port', (process.env.PORT || 3000));
app.use(express.static(path.join(__dirname,'client')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use('/api', items);
app.all('/*', function(req, res, next) {
// Just send the index.html for other files to support HTML5Mode
res.sendFile(path.join(__dirname, './client', 'index.html'));
});
app.listen(app.get('port'), function() {
console.log('Node app is running on port', app.get('port'));
});
package.json (server side)
{
"name": "namex",
"version": "1.0.0",
"description": "descx",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.15.2",
"ejs": "^2.5.5",
"express": "^4.14.0",
"mongojs": "^2.4.0",
"ng2-pagination": "^1.0.1"
}
}
systemjs.config.js
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// angular bundles
'#angular/core': 'npm:#angular/core/bundles/core.umd.js',
'#angular/common': 'npm:#angular/common/bundles/common.umd.js',
'#angular/compiler': 'npm:#angular/compiler/bundles/compiler.umd.js',
'#angular/platform-browser': 'npm:#angular/platform-browser/bundles/platform-browser.umd.js',
'#angular/platform-browser-dynamic': 'npm:#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'#angular/http': 'npm:#angular/http/bundles/http.umd.js',
'#angular/router': 'npm:#angular/router/bundles/router.umd.js',
'#angular/forms': 'npm:#angular/forms/bundles/forms.umd.js',
// other libraries
'ng2-pagination': 'npm:ng2-pagination/dist/',
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
'angular2-jwt': 'node_modules/angular2-jwt/angular2-jwt.js'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
'angular2-jwt': {
"defaultExtension":'js'
},
rxjs: {
defaultExtension: 'js'
},
'ng2-pagination': {
defaultExtension: 'js', main: 'ng2-pagination.js'
}
}
});
})(this);
index.html
<!DOCTYPE html>
<html>
<head>
<title>ngAuth0 App</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
<link rel="stylesheet" href="styles.css">
<link href="https://fonts.googleapis.com/css?family=Philosopher" rel="stylesheet" type="text/css">
<script src="https://cdn.auth0.com/js/lock/10.6/lock.min.js"></script>
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<base href="/">
<my-app>Loading ...</my-app>
</body>
</html>
You should copy polyfills with the app when deployed node_modules is not available.
if you copy them to the same folder where systemjs.config.js
<script src="shim.min.js"></script>
<script src="zone.js"></script>
<script src="Reflect.js"></script>
<script src="system.src.js"></script>
I am new to angular 2 and systemjs, and I have a sample node.js project where I'm trying to map an angular 2 app in the subfolder './client/dashboard' to a sub URL 'localhost:3000/dashboard' using the express.static middleware:
app.use('/dashboard', express.static(__dirname + '/client/dashboard', { maxAge: 86400000 }));
angular 2 app folder structure
my index.html has the following code:
<base href="/dashboard">
<link rel="stylesheet" href="dashboard/styles.css">
<script src="dashboard/node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="dashboard/node_modules/systemjs/dist/system.src.js"></script>
<script src="dashboard/node_modules/rxjs/rx.js"></script>
<script src="dashboard/node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="dashboard/node_modules/angular2/bundles/router.dev.js"></script>
<script src="dashboard/node_modules/angular2/bundles/http.dev.js"></script>
<script>
System.config({
baseURL: '/dashboard',
// paths: {
// '*': 'dashboard/*'
// },
map: {
app: '/dashboard/app',
rxjs: '/dashboard/node_modules/rxjs',
angular2: '/dashboard/node_modules/angular2'
},
packages: {
app: { format: 'register', defaultExtension: 'js' },
rxjs: { defaultExtension: 'js' },
angular2: { defaultExtension: 'js' }
}
});
System.import('app/main').then(null, console.error.bind(console));
</script>
The only errors I'm getting are a 'require is not defined' on rx.ts and a 404 on a css file (see attached pic chrome errors)
If I simply map the angular 2 app directory to '/', I still get the arbitrary 'require is not defined' error on rx.ts, but the page loads properly, so I'm pretty sure that isn't the issue. The only other error I'm seeing is the css error. Any ideas what the issue could be? tia
Perhaps it's because you included twice rxjs and angular2: one using script elements and one within the SystemJS configuration.
Why do you need to define them in the SystemJS configuration?
Edit
This should be enough:
<base href="/dashboard">
<link rel="stylesheet" href="dashboard/styles.css">
<script src="dashboard/node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="dashboard/node_modules/systemjs/dist/system.src.js"></script>
<script src="dashboard/node_modules/rxjs/rx.js"></script>
<script src="dashboard/node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="dashboard/node_modules/angular2/bundles/router.dev.js"></script>
<script src="dashboard/node_modules/angular2/bundles/http.dev.js"></script>
<script>
System.config({
baseURL: '/dashboard',
map: {
app: '/dashboard/app'
},
packages: {
app: {
format: 'register', defaultExtension: 'js'
}
}
});
System.import('app/main').then(null, console.error.bind(console));
</script>