How to load handlebars with requireJS - requirejs

I am trying to load the handlebars with require js, but I am getting undefined.
requirejs.config({
baseUrl: 'scripts',
paths: {
jquery: ['https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery',
'jquery-3.5.1'],
popper: ['https://unpkg.com/#popperjs/core#2/dist/umd/popper.js'],
handlebars: ['handlebars-v4.7.6.js'],
}
});

Related

Server side rendering with Webpack and Express at runtime

Is it possible to render template files (such as Pug or Handlebars) dynamically at runtime using Webpack and Express?
My issue is when loading my root page (index.pug), the html loads however no assets are loading.
Example:
app
.set('views', path.join(__dirname, 'views'))
.set('view engine', 'pug')
.use('/', function(req, res) {
res.render('index', {some: 'param'})
})
If I remove the '/' route handler, the page loads with all of the assets just fine.
Client webpack.config.js file:
module.exports = {
entry: {
main: ['webpack-hot-middleware/client?path=/__webpack_hmr&timeout=60000', './index.js', './css/main.css']
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: '[name].js'
},
mode: 'development',
target: 'web',
devtool: '#source-map',
module: {
rules: [
{
test: /\.pug$/,
use: ['html-loader?attrs=false', 'pug-html-loader']
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: './views/index.pug',
filename: "./index.html",
excludeChunks: [ 'app' ]
})
]
}
Server webpack.server.config.js:
module.exports = (env, argv) => {
return ({
entry: {
app: 'app.js',
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: '[name].js'
},
target: 'node',
node: {
// Need this when working with express, otherwise the build fails
__dirname: false, // if you don't put this is, __dirname
__filename: false, // and __filename return blank or /
},
externals: [nodeExternals()], // Need this to avoid error when working with Express
module: {
rules: [
{
// Transpiles ES6-8 into ES5
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
})
}
You can make it work in 2 easy steps (based on the code above).
In server change the views path to where your built template is going to be. In the example above it's going to be inside the dist folder
app
.set("views", "./dist");
.set('view engine', 'pug')
.use('/', function(req, res) {
res.render('index', {some: 'param'})
})
At this point, after we run a build script and start the server we would get a message that there's no view in dist folder, which is correct because engine is looking for a template and all we have are html files
In webpack.config.js in HtmlWebPackPlugin we need to leave a filename as a template
plugins: [
new HtmlWebPackPlugin({
template: './views/index.pug',
filename: "./index.pug",
excludeChunks: [ 'app' ]
})
]
And that's it. Now template engine will find index.pug in dist with injected style and script and generate html from it
Note: In production it's important to set a path for static files, otherwise you won't get your css displayed even though the link tags were injected correctly
app.use(express.static(__dirname));
The above solution worked for me when I run into the same problem, but with the ejs template. I couldn't find the answer to it anywhere, so hopefully, it will save someone hours of frustration.

How to use webpack-dev-middleware with feathers / express?

I'm trying to get a feathersjs app started with a reactjs frontend. Using the webpack-dev-middleware and webpack-hot-middleware, I should be able to simply extend the feathers app with all this webpack stuff during development. The only problem is always end up getting a feathers 404 page whenever I fetch the js file from webpack.
Currrently, here's my directory structure:
/feathers/public/index.html
/feathers/src/app.js
/react/src/index.js
/react/webpack.config.js
/react/develop.js
/feathers/src/app.js is is default feathers app, serves static files from the public folder.
.use('/', serveStatic( app.get('public') ))
In /react/develop.js, I'm requiring the feathers app and extending it with the webpack middlewares.
const app = require('../feathers/src/app');
const config = require('./webpack.config');
const path = require('path');
const webpack = require('webpack');
var compiler = webpack(config);
app.use(require('webpack-dev-middleware')(compiler, {
publicPath: '/',
stats: {colors: true},
}));
app.use(require('webpack-hot-middleware')(compiler));
const port = app.get('port');
const server = app.listen(port);
server.on('listening', () =>
console.log(`Feathers application started on ${app.get('host')}:${port}`)
);
Sadly this isn't working at all. For reference, here's my /react/webpack.config.js
var webpack = require("webpack")
module.exports = {
devtool: 'source-map',
entry: [
'webpack-hot-middleware/client',
'src/index.js'
],
output: {
path: '/',
filename: "bundle.js",
},
module: {
loaders: [
{ test: /\.js$/, loader: "babel", exclude: /node_modules/, query: { presets: ['es2015', 'react', 'stage-0'] } },
{ test: /\.(svg|png|jpe?g|gif|ttf|woff2?|eot)$/, loader: 'url?limit=8182' },
]
},
resolve: {
root: [
__dirname,
__dirname + '/src',
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
]
}
And /feathers/public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React App</title>
</head>
<body>
<div id="root"></div>
<script src="bundle.js"></script>
</body>
</html>
I've tried messing around with the publicPath stuff but no luck. Any ideas how to get this working? I've spend a solid 2 hours on this and got no where. Here's a link to the repo I'm working with for more context.
I see from your repository that you got this to work by including the webpack dev/hot middlewares in the proper place, in feathers/src/middleware/index.js where they will be used before Feathers' notFound middleware returns the 404. Middleware order matters!
Exporting a function for this purpose like you did in react/middleware.js is a clean solution to this problem, because it isolates the concern of setting up the webpack middleware from the backend itself (all the webpack stuff stays in the frontend).
Hope this helps anyone else!

webpack-dev-middleware and Express - can't get them to collaborate

I am trying to set up my first project using Webpack and Express but somehow I am doing something wrong.
This is what I did:
1. CREATED SAMPLE PROJECT
Created a sample project using express-generator. My folder structure is something like:
express-project
-app.js
-webpack.config.js
-public
-javascripts
-modules
-build
2. SET UP HANDLEBARS
Set up handlebars as view/template engine and created a couple of routes
3. WEBPACK CODE
Created the Webpack specific code/configuration as follows
webpack.config.js
var webpack = require('webpack');
var path = require('path');
var webpackHotMiddleware = 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=2000&overlay=false';
module.exports = {
resolve: {
alias: {
handlebars: path.resolve('public/vendor/handlebars-v4.0.5.js'),
bootstrap: path.resolve('public/vendor/bootstrap/js/bootstrap.js'),
pubsub: path.resolve('public/vendor/ba-tiny-pubsub.js')
}
},
context: path.resolve('public/javascripts'),
entry: {
cart: ['./modules/cart', webpackHotMiddleware],
index: ['./modules/products.js', webpackHotMiddleware],
vendor: ['bootstrap', 'pubsub', webpackHotMiddleware]
},
output: {
path: path.resolve('public/javascripts/build'),
publicPath: 'javascripts/build/',
filename: '[name].js',
chunkFilename: "[id].js"
},
module: {
loaders: [
// some loaders here
]
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
}
app.js
// some code before
var app = express();
(function() {
// Step 1: Create & configure a webpack compiler
var webpack = require('webpack');
var webpackConfig = require(process.env.WEBPACK_CONFIG ? process.env.WEBPACK_CONFIG : './webpack.config');
var compiler = webpack(webpackConfig);
// Step 2: Attach the dev middleware to the compiler & the server
app.use(require("webpack-dev-middleware")(compiler, {
noInfo: false,
publicPath: webpackConfig.output.publicPath,
stats: {
colors: true
}
}));
// Step 3: Attach the hot middleware to the compiler & the server
app.use(require("webpack-hot-middleware")(compiler, {
log: console.log,
path: '/__webpack_hmr',
heartbeat: 10 * 1000
}));
})();
// some code after
4. JS CODE ON TEMPLATE
Then on the handlebars page I require the bundled javascripts
<script src="javascripts/build/common.js"></script>
<script src="javascripts/build/vendor.js"></script>
<script src="javascripts/build/cart.js"></script>
5. NPM START
Finally if I start the server using the standard npm start I see in the shell that webpack bundles everything with no errors but if I go to localhost:3000/ it does not find any of the assets created by Webpack. Instead if I run webpack to create the various bundles as if I were on production, everything is created correctly and it works as expected.
Hope someone can figure out what I am doing wrong.
Thanks
I managed to figure out what was causing the problem, by adding a slash in these 2 lines everything started to work properly:
context: path.resolve('public/javascripts/'),
path: path.resolve('public/javascripts/build/'),

systemjs - mapping to different URL

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>

RequireJs Module in node always returns undefined when using in a grunt task

I've a small config file that I need in frontend and in my grunt task.
js/config.js:
define(function() {
return [
{
id: 'demo',
displayName: 'Demo'
}
];
});
I can load the file in frontend without problems it also work in node.
var requirejs = require('requirejs');
requirejs.config({
nodeRequire: require,
baseUrl: './js'
});
var config = requirejs('config')
But when I try to load the same file in a grunt task it returns undefined:
requirejs.config({
nodeRequire: require,
baseUrl: './js'
});
grunt.registerTask('lala', function () {
var config = requirejs('config')
});
The problem was that the I require requireJs outside of the module.exports function. So this works after all:
module.exports = function(grunt) {
var requirejs = require('requirejs');
requirejs.config({
nodeRequire: require,
baseUrl: './js/cfe/app/platforms/as'
});
grunt.registerTask('lala', function () {
var config = requirejs('config')
});
}
This code works for me. First I've installed requirejs:
cd /path/to/code/directory
npm install requirejs
Then in my app.js:
var requirejs = require('requirejs');
requirejs.config({
nodeRequire: require,
baseUrl: './js'
});
var config = requirejs('config');
console.log(config);
And in the js/config.js:
define(function() {
return [
{
id: 'demo',
displayName: 'Demo'
}
];
});
When I run it, I get the correct result:
$ node app.js
[ { id: 'demo', displayName: 'Demo' } ]
I'm using Node v0.10.1.

Resources