Why can't docker see my template file in my node - node.js

Run directly from my local directory, this works fine. I type ‘localhost:3002’ in the browser and up pops my ‘find.html’ page. However, when I dockerise it and try the same command, it craps out complaining that macro.njk can’t be found.
Dockerfile:
FROM node:14.17.5
ENV NODE_ENV=production
WORKDIR /application
COPY ["package.json", "package-lock.json*", "./" ]
RUN npm install --production
COPY . .
CMD ["node", "app.js"]
In find.html:
{% extends "layout/layout.njk" %}
Nunjucks setup in app.js:
const express = require('express');
const path = require('path');
const nunjucks = require('nunjucks');
nunjucks.configure(['views',
path.join(__dirname, 'node_modules/motluk-frontend/'),
path.join(__dirname, 'node_modules/motluk-frontend/motluk/components/'),
path.join(__dirname, 'app/views/'),
], {
autoescape: true,
express: app,
});
// view engine setup
app.set('views', path.join(__dirname, 'app/views'));
app.set('view engine', 'html');
app.use(bodyParser.urlencoded({
extended: true,
}));
directory setup:
/app/views/layout/layout.njk
/app/views/pages/find.html
The error message I get:
Template render error: (/application/app/views/pages/find.html)
Error: template not found: input/macro.njk

Related

Express routes don't return data within Docker conatiner

When the app starts, the home page immediately makes a request to my googleRoute to retrieve some review data.
When ran locally and visiting localhost:3001 the app starts up and displays the data fine.
When ran via docker and visiting localhost:3001 the app starts up and the data is 'undefined' as if the route never returned any data back.
Below is my code...
Express App Index.js:
const express = require('express')
const awsRouter = require('./routes/aws-route')
const googleRouter = require('./routes/google-route')
const dotenv = require('dotenv');
const path = require('path');
const PORT = process.env.PORT || 3001;
const app = express();
// middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
//routes
app.use("/api/aws", awsRouter);
app.use("/api/google", googleRouter);
app.use(express.static(path.join(__dirname, '../react-app/build')));
app.get('/', (req,res) => {
res.sendFile(path.join(__dirname, '../react-app/build/index.html'));
});
app.listen(PORT, () => {
console.log(`Server listening on ${PORT}`);
});
My Dockerfile:
# pull official base image
FROM node:13.12.0-alpine AS ui-build
# set working directory
WORKDIR /app
COPY react-app/ ./react-app
RUN cd react-app && npm install && npm run build
FROM node:13.12.0-alpine AS server-build
WORKDIR /root/
COPY --from=ui-build /app/react-app/build ./react-app/build
COPY express-app/package*.json ./express-app/
COPY express-app/index.js ./express-app/
COPY express-app/routes ./express-app/routes
RUN cd express-app && npm install
EXPOSE 3001
CMD [ "node", "./express-app/index.js" ]
After adding log statements to my routes, I noticed that I was able to reach the routes just fine however my environment variables were undefined.
To fix this I used the --env-file flag as mentioned here to reference my environment variables from my .env file

AgoraIO Web + Heroku

I'm trying to push github repo LargeGroupVideoChat-Web-Webpack to Heroku.
Locally it works fine, with these scripts in package.json file:
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --config ./scripts --mode development",
"build": "cross-env NODE_ENV=production webpack --config ./scripts --mode production"},
And webpack settings in index.js file:
module.exports = {
entry: {
index: "./src/index.js",
},
devtool: "inline-source-map",
module: loaders,
plugins,
resolve: {
extensions: [ ".js" ],
},
output: {
filename: "[name].[hash].js",
path: path.resolve(__dirname, distPath),
}, ...
However, after pushing to Heroku it crashes with error. I added server.js file with this code:
const express = require('express');
const path = require('path');
const port = process.env.PORT || 8080;
const app = express();
// the __dirname is the current directory from where the script is running
app.use(express.static(__dirname));
// send the user to index html page inspite of the url
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'index.html'));
});
app.listen(port);
It runs ok, but it only serves index.html file, and webpack bundle is not linked. Is there a fast way to push the app to Heroku? Or I have to rewrite webpack settings somehow?
Ok, the server.js file solved the problem (from another repo):
var path = require('path');
var express = require('express');
var app = express();
app.use(express.static(path.join(__dirname, 'dist')));
app.set('port', process.env.PORT || 8080);
var server = app.listen(app.get('port'), function() {
console.log('listening on port ', server.address().port);
});

Express path missing after refresh

/styles.css goes missing after I do a page refresh.
Here's my package.json build script:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"clean": "rimraf dist",
"start": "nodemon -e js,css,handlebars -i scss --watch app --exec babel-node app/app.js",
"build": "npm run clean && mkdir -p dist && babel app -s -D -d dist",
"serve": "node dist/app.js",
"postinstall": "npm run build"
},
The problem only exists in the dist version.
I run npm run build, then npm run serve.
What this does is build and copy every file to /dist folder.
App is served in /dist/app.js.
So /styles.css loads on initial load, but subsequent loads shows request is cancelled. Tried loading the site with a private window but the problem persists. It loads only once again, after reloading the server.
screenshot of request
Here's app.js:
import bodyParser from 'body-parser'
import express from 'express'
import exphbs from 'express-handlebars'
import path from 'path'
import sassMiddleware from 'node-sass-middleware'
const PORT = process.env.PORT || 3000
const app = express()
// Config
app.locals.config = require('./config.json')
// Views and handlebars view engine
const hbs = exphbs.create({
defaultLayout: 'main',
layoutsDir: 'app/views/layouts',
helpers: {
sitename: function () {
return app.locals.config.sitename
},
ga: function () {
if (process.env.NODE_ENV === 'production') {
...
}
},
},
})
app.engine('handlebars', hbs.engine)
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'handlebars')
// Body parser
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: false}))
// Sass middleware
app.use(sassMiddleware({
src: path.join(__dirname, 'public/scss'),
dest: path.join(__dirname, 'public/css'),
outputStyle: 'compressed',
sourceMap: true,
}))
// Static folder
app.use(express.static(path.join(__dirname, 'public')))
// Routes
app.use(require('./routes/index.js'))
const server = app.listen(PORT, () => console.log(`listening at port ${PORT}...`))
I load /styles.css with this in my view template:
<link rel="stylesheet" href="/styles.css">
Update and solved:
I should had added that my folder structure looks like this:
/app
- public/
- css
- js
- scss
- routes/
- ...
- views/
- ...
Solved the problem by changing the the src path in views template:
<link rel="stylesheet" href="/css/styles.css">
Had to add prefix to node-sass-middleware too for local development.
// Sass middleware
app.use(sassMiddleware({
src: path.join(__dirname, 'public/scss'),
dest: path.join(__dirname, 'public/css'),
prefix: '/css',
outputStyle: 'compressed',
sourceMap: true,
}))

node-sass-middleware not compiling

Im trying to get the node-sass-middleware working with with express. The app runs with no errors
...(modules)
var sassMiddleware = require('node-sass-middleware');
var routes = require('./routes/index');
var app = express();
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
//---- LOAD SASS -----//
// adding the sass middleware
var srcPath = __dirname + '/scss';
var destPath = __dirname + '/public/stylesheets';
app.use(sassMiddleware({
src: srcPath,
dest: destPath,
debug: true,
outputStyle: 'compressed'
}));
app.use(express.static(path.join(__dirname, 'public')));
Can anyone see anything wrong with the way I'm attempting to compile the sass?
file structure :
app
controllers
routes
public
-stylesheets
scss
...
This is how app.js should be:
app.use(sassMiddleware({
src: srcPath,
dest: destPath,
debug: true,
outputStyle: 'compressed'
}),
express.static(path.join(__dirname, 'public')));
Also your main scss file should be named style.scss and be inside scss/stylesheets/ directory.
You should see a log like this, if you have correctly loaded the module:
source : /Users/abc/Desktop/SO/SO_node/scss/stylesheets/style.scss
dest : /Users/abc/Desktop/SO/SO_node/public/stylesheets/stylesheets/style.css
read : /Users/abc/Desktop/SO/SO_node/public/stylesheets/stylesheets/style.css
render : /Users/abc/Desktop/SO/SO_node/scss/stylesheets/style.scss
A problem could also be that you want to compile scss
instead of sass. Therefore set indentedSyntax to false.
app.use(require('node-sass-middleware')({
src: path.join(__dirname, 'scss'),
dest: path.join(__dirname, 'public'),
indentedSyntax : false,
sourceMap: true
}));
Or remove it completly. Express-generator adds this value on default.
Better go for grunt-sass. Simple configuration, automated task (thanks to grunt) and also faster compiling time because of libsass, which is the C version of the original Ruby compiler for SASS. Compile sass/scss files in 0.3 seconds instead of 3.

How do you install SASS with Express?

I am creating a node.js app with Express and socket.io.
I want to use SASS and I see there is a npm package for it, what I don't understand is how do I link between the SASS npm and the app and make it parse the SASS?
UPDATE:
I used SASS middleware https://github.com/andrew/node-sass installed it and included it the following way:
sass = require('node-sass');
app.configure(function(){
app.set('port', process.env.PORT || 3000);
/* other stuff */
sass.middleware({
src: __dirname + '/public/stylesheets/sass',
dest: __dirname + '/public/stylesheets',
debug: true
});
});
But it still doesn't work
You need to use the sass middleware, for example this one.
Quoting from docs:
var server = connect.createServer(
sass.middleware({
src: __dirname
, dest: __dirname + '/public'
, debug: true
}),
connect.static(__dirname + '/public')
);
in case of using express, just add:
app.use(
sass.middleware({
src: __dirname + '/sass', //where the sass files are
dest: __dirname + '/public', //where css should go
debug: true // obvious
})
);
to your app.configure() call.
Of course on production systems it's a better idea to precompile sass to css.
update
In the example above the middleware will look for sass files in __dirname + '/sass/css'. Also by default it looks for files with .scss extension. There doesn't seem to be an option to change the extension.
If you are using express-generator Then try
express --view=ejs --css=sass
Here is a solution based on various sources including the threads/comments above:
node:
var connect = require('connect');
var sass = require('node-sass');
var srcPath = __dirname + '/sass';
var destPath = __dirname + '/public/styles';
var server = connect.createServer(
sass.middleware({
src: srcPath,
dest: destPath,
debug: true,
outputStyle: 'expanded',
prefix: '/styles'
}),
connect.static(__dirname + '/public')
);
html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="styles/main.css">
etc
file system:
rootDirectory / server.js (this is the node app)
rootDirectory / public / styles / (this is where the compiled scss files will appear)
rootDirectory / sass / main.scss
This works for me and I've forked the example at:
node-sass-example
here:
node-sass-example using prefix
Looks like implementation has changed a bit for Express. I had to do this instead:
npm install node-sass-middleware --save
then
var sass = require('node-sass-middleware');
app.use(
sass({
src: __dirname + '/sass', // Input SASS files
dest: __dirname + '/public', // Output CSS
debug: true
})
);

Resources