I am building a nodejs app using Handlebars as my template engine. I have a template like this one (template.hbs):
<html>
<head></head>
<body>
{{ my_var }}
</body>
</html>
I wonder if I can work (write code) with this file while using on node a minified version ( that will be compiled and delivered for the user ) like this (minified_template.hbs):
<html><head></head><body>{{ my_var }}</body></html>
I mean, I would like some program to be running all time, watching for changes on "template.hbs" and generating "minified_template.hbs". This way I can save bandwidth and money. Is there such a program that can do it? I've heard of Webpack but after searching on google I am still no sure it can do this kind of job.
Thanks in advance.
I have found the answer to my question. It's name is "Gulp":
Install nodejs, then run on commandline:
npm install -g gulp
npm install --save-dev gulp-minify-html
create a file named "gulpfile.js" as:
var gulp = require('gulp');
var minifyHtml = require("gulp-minify-html");
gulp.task('minify-views', function () {
gulp.src('./views/*.html')
.pipe(minifyHtml())
.pipe(gulp.dest('./views_minified'));
});
gulp.task('watch-views', function () {
gulp.src('./views/*.html')
.pipe(minifyHtml())
.pipe(gulp.dest('./views_minified'));
gulp.watch(["./views/*.html"],['minify-views']);
});
Then, from commandline, run:
gulp watch-views
When anny file under the "views" folder is modified, it gets minified by gulp and saved with tha same name to the folder named "views_minified".
Related
I am new in laravel. I installed npm before some days. And now I need editor in my application. So I have installed it via npm using "npm install summernote --save-dev" command. And add below lines in my app.js
require('./bootstrap');
require('summernote');
require('summernote/dist/summernote.css');
require('summernote/dist/summernote.js');
require('jquery');
$(document).ready(function() {
$('#content_editor').summernote();
});
and then compiled the assets via "npm run dev" command. But it will display 2 textarea, one that is in my html and second is summernote textarea. It is not displaying toolbars and other things. It is displaying only textarea.
Can anybody please help me to resolved this problem. I am newly learning laravel. So, I don't have deep knowledge of packages. I just want to display it without including css and js to header. I need it via webpack.
This code in app.js with Laravel 8 does work:
require('./bootstrap');
require('summernote');
require('summernote/dist/summernote.css');
require('summernote/dist/summernote.js');
import $ from 'jquery';
window.$ = window.jQuery = $;
$(document).ready(function () {
$('.summernote').summernote();
});
The trick is in webpack.mix.js configuration file. It should appear something like:
const mix = require('laravel-mix');
let path = require('path');
mix.webpackConfig({
resolve: {
alias: { jQuery: path.resolve(__dirname, 'node_modules/jquery/dist/jquery.js') }
}
});
// Into app.js, you require 'summernote' as always
mix.js('resources/js/app.js', 'public/js');
Source: https://laracasts.com/discuss/channels/javascript/summernote-and-webpack
I need some help.
I'm looking for a way to generate (or update if the file already exists) a .css file that is a conversion by an .scss file. All of this when compiling.
Explaining this in a better way :
I'm writing some code, everything is ok and I decide to save. Perfect. ctrl+s and the app run perfectly. Nice. Now I've added a style.scss file somewhere (it doesn't really matter the path). How do I "tell" to the compiler that everytime he compile he also has to 'take' this .scss file, convert it in a .css file, and put it in a specific path?
Well, I found a way to do what I needed to do.
I've created my gulpfile.js in this way :
var gulp = require('gulp');
var sass = require('gulp-sass');
var watch = require('gulp-watch');
gulp.task('styles', function () {
gulp.src('src/app/sass/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./css/'));
});
gulp.task('watch', function () {
gulp.watch('./sass/**/*.scss', ['styles']);
});
And added this command to package.json :
"try": "gulp watch && ng s"
the problem is that if in the cli I run the command npm run try it will never start my application, because the watch is an endless stream.
How can I have the watch and the app running both at the same time?
*Edit
Found the solution using concurrently
I have a gulp script that concatenate and minify my JavaScript.
With the gulp-html-replace plugin I can replace all my JS dependancies by the concatened file in my index.html.
I end up with a dev version (/dev/index.html), with all the single JS files included (easier for debugging) and a production version,with all JS concatened (/prod/index.html).
For now I have a config flag (in NodeJS) in a config.js file and I do the following :
res.render(((config.build === 'prod') ? './prod' : './dev') + 'myPage')
But I'm not really happy with this solution as it adds a lot of code and it's easy to forget to write this code.
Is there a better solution ?
Does this solution take place in Gulp
(by havign a gulp prod and a gulp dev for example)
Or does it take place in Node (by setting up a virtual directory for example)
I am new to this npm/gulp/node workflow and not sure of what belongs where
The way I like to do it is by maintaining two separate versions for index.html.
index-development.html for dev environment and index-production.html for production environment.
The index-development.html includes all the scripts and css (non minified and concatenated) and index-production.html as minified and concatenated scripts and css links.
I construct index.html from gulp script.
By default the index-development.html will be deployed.
If I specify parameter p to the gulp script, it will deploy index-production.html
No need to update the file path of the file to be served in your express router.
First do
npm install yargs
In gulp, I include
var argv = require('yargs').argv;
Check if parameter p (gulp -p) is passed to the gulp (p for production) with
var isProduction = argv.p;
and then,
if(isProduction){
taskSequence = ['combineControllers','combineServices','productionsIndex','startServer'];
} else{
taskSequence = ['developmentIndex','startServer'];
}
gulp.task('default', taskSequence);
gulp.task('startServer', function(){
exec('npm start', function (err, stdout, stderr) {
console.log(stdout);
console.log(stderr);
cb(err);
});
});
gulp.task('productionsIndex', function(done) {
return gulp.src('./www/index-productions.html')
.pipe(concat('index.html'))
.pipe(gulp.dest('./public/'));
});
gulp.task('developmentIndex', function(done) {
return gulp.src('./www/index-development.html')
.pipe(concat('index.html'))
.pipe(gulp.dest('./public/'));
});
This way, your index.html file will be constructed dynamically without having to change of the code in your express and you can serve it like
res.render('index');
if you want to user myPage.html everywhere, just replace index.html and index in the code above with myPage.html and myPage.
EDIT:
To start your application in development environment, simply run gulp
To start your application in production environment, simply run gulp -p
Simple!
in your app initialization process you can set the path of your views.
app.set('views', process.cwd() + ((config.build === 'prod') ? '/prod' : '/dev'));
Now you can call the render function like this:
res.render('myPage');
Metalsmith portrays itself as a ridiculously simple static site generator. I'm trying to write the most basic of sites just to get myself familiar with the basics of the software, but I can't seem to get even that to build. Here's my folder structure:
|- build/
|- index.js
|- src/
|-index.html
|- templates
|-index.hbt
My index.js file:
var Metalsmith = require('metalsmith');
Metalsmith(__dirname)
.destination('./build')
.build();
My index.html file:
---
title: Home
template: index.hbt
---
And my index.hbt template:
<!doctype html>
<html>
<head>
<title>FOO</title>
</head>
<body>
something
</body>
</html>
My understanding is that the build command should look through the src directory and parse any file it finds with that YAML stuff at the top. So it should look at index.html, see that it renders using the templates/index.hbt template, and basically just move the file into build/index.html. But when I run node index.js I get absolutely nothing. No progress indicator, no "Done building your stuff!" message, just a blinking command prompt line. My build directory is empty. Obviously something is breaking, but there are no logs to check, and no status messages to google. What am I doing wrong? Shouldn't there be at least one page created in the build directory?
Found the answer, in a comment on a tutorial, of all places: https://blog.robinthrift.com/2014/04/14/metalsmith-part-1-setting-up-the-forge/. It's also on the github examples: https://github.com/segmentio/metalsmith
According to those links, you need to include an error callback on the .build() function:
Metalsmith(__dirname)
.build(function(err) {
if (err) throw err;
});
In addition to the error callback issue, which you've already identified, I think you're missing a few things in your files. True, Metalsmith is very simple, but its simplicity means that a lot of the functionality (like support for templates) is brought by modules that you need to install and include explicitly.
You say the content of your index.js file is:
var Metalsmith = require('metalsmith');
Metalsmith(__dirname)
.destination('./build')
.build();
Is that everything you have in you index.js? If you want to use Handlebars templates, you need to explicitly add the metalsmith plugin that handles templates, and instruct it to use handlebars:
var Metalsmith = require('metalsmith');
var templates = require('metalsmith-templates');
Metalsmith(__dirname)
.destination('./build')
.use(templates('handlebars'))
.build();
And make sure that you install the metalsmith-templates and handlebars modules from npm.
Also, you probably know this, but in your index.hbt, you'll need to change
<title>FOO</title>
to
<title>{{ title }}</title>
in order to load the title metadata from index.html.
Let me know if this gets you going, or if you need more help.
I'm using Gulp and Browserify to package my Javascript into 2 separate bundles: application.js and vendor.js.
How do I bundle the vendor package if my vendor libraries are installed with Bower?
In my gulpfile, I'm using the following modules:
var gulp = require("gulp");
var browserify = require("browserify");
var debowerify = require("debowerify");
var source = require("vinyl-source-stream");
Assuming that I have only the Phaser framework installed with bower (for this example), my Gulp task to create the application package looks like this:
gulp.task("scripts-app", function () {
browserify("./app/javascripts/index.js")
.external("phaser")
.pipe(source("application.js"))
.pipe(gulp.dest("./tmp/assets"));
});
Meanwhile, the vendor task looks like this:
gulp.task("scripts-vendor", function () {
browserify()
.transform(debowerify)
.require("phaser")
.pipe(source("vendor.js"))
.pipe(gulp.dest("./tmp/assets"));
});
When I run this Gulp task, I get an error that states Error: Cannot find module 'phaser' from and then all the directories it search through (none of which are the bower_components directory).
Any ideas about how to package these up successfully are greatly appreciated. Thanks!
Answered my own question:
When using require in the Gulp task, you need to supply a path to a file, not just a name.
gulp.task("scripts-vendor", function () {
browserify()
.transform(debowerify)
.require("./bower_components/phaser/phaser.js")
.pipe(source("vendor.js"))
.pipe(gulp.dest("./tmp/assets"));
});
Notice that require("phaser") became require("./bower_components/phaser/phaser.js").
Doing this works, although the bundle takes forever to build (around 20 seconds). You're probably better of just loading giant libraries/frameworks directly into your app through a <script> tag and then using Browserify Shim.
This let's you require() (in the NodeJS/Browserify sense) global variables (documentation).
Seems like you figured out how to require the bower file. Hopefully you'll only have to bundle it once initially, and not every build. Including the library via a script tag isn't a bad idea. Another technique I'm using is to use scriptjs (a polyfill would work too), to async load whatever vender libraries I need, but make sure to include any/all require's after the script loads. For example, your index.js could be like:
$script.('/assets/vendor', function() {
var phaser = require('phaser');
//rest of code
});
It's especially nice for loading cdn files or having the ability to defer loading certain libraries that aren't necessarily used in the core app by every user, or loading libraries after client-side routing.