I have a directory app/server/views/ wherein all the jade files are present. As my application is now beginning to have more jade files, I thought of structuring app/server/views/ based on category of actors for simplicity & maintainence. Something like:
app/server/views/admin/task1.jade
app/server/views/admin/task2.jade
app/server/views/superadmin/task1.jade
app/server/views/superadmin/task2.jade
app/server/views/user/task1.jade
app/server/views/user/task2.jade
If all the jade files are present inside /app/server/views/ directory, my index.js file has no problem in loading the jade files. However on structuring per above mentioned directory format, I run into issues:
server.views({
engines:
{
jade: require('jade')
},
path: [ __dirname + "/app/server/views/admin", __dirname + "/app/server/views/superadmin", __dirname + "/app/server/views/user" ]
});
With the above index file, my jade files won't load.
I don't think path can be an array. From the docs, I gather that it should be one directory.
Something like path: Path.join( __dirname, 'app/server/views' ) then call the templates from your controller as reply( 'admin/task1', ....).
If you can determine your actor's role programatically and have exactly the same code, then something like reply( actorsRole + '/task1' ) should do the trick.
Related
Im getting started with webpack but one thing I cannot for the life of me work out is how to take a folder (with possible nested folders), full of .pug templates, and simply compile them to static html and put them in the output folder, maintaining any nested folder structure for each output html file that was in the source templates folder...
I dont want to have to manually specify each individual .pug file, and I definitely dont want webpack to try and parse the .pugs into JS and then attempt to require/import any of the imgs/fonts etc in the pug files and then complain about it, Im just after a basic, static 1:1 compile, pug file in, html file out. Why is it so hard to do that?
Use pug-html-loader to convert .pug to .html file. Use file-loader to copy the file to desired location. Don't use html-loader as you don't want to process resources used by the generated file.
You will end up something like this in your loader rules (untested, webpack 1 syntax, you may need to tweak it for webpack 2)
{
test: /\.pug$/,
loaders: ['file-loader?name=[path][name].html', 'pug-html-loader?pretty&exports=false']
}
Next you need to require all your pug files in your entry file
function requireAll (r) { r.keys().forEach(r); }
requireAll(require.context('./', true, /\.pug$/));
This can be done very simply with only html-webpack-plugin and pug-loader.
webpack.config.js
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// No javascript entrypoint to evaluate. Let the plugin do the heavy lifting
entry: {},
// Translate Pug to HTML
module: { rules: [ { test: /\.pug$/, use: 'pug-loader' } ] },
// Save HTML to file
plugins: [ new HTMLWebpackPlugin({ template: './src/index.pug' }) ]
};
./src/index.pug
doctype html
html(land="en")
head
include path/to/another.pug
...
Got this information from https://extri.co/2017/05/23/using-htmlwebpackplugin-and-pug/ and you can also go further to import css and javascript as normally done with html-webpack-plugin.
What is the best practice to use ExpressJS, VueJS and Jade together?
It's a little bit stupid question, but do I need convert Jade to HTML (like I know, because VueJS can't serve Jade files)?
Do i need serve a Jade or converted HTML index file in ExpressJS?
Without using VueJS, code in my index.js file is something like this:
app.set("view engine", "pug");
app.set("views", __dirname + "/templates");
app.get('/', function(req, res){
res.render("index");
});
And when I want to use Gulp, then.. how?
ExpressJS lives at the back-end and uses your .jade (actually renamed as .pug) templates to generate and serve html. And that's all, next, you can use Vue (client side framework) to develop anything you want.
So, what you can do is, create a .jade template (.pug) like this:
...
body
p {{message}}
script(src='path/to/vue.js')
script.
const app = new Vue({
el: 'body',
data(){
return {
message: 'Hello World!'
}
}
});
It is a simple example. The important thing is that you just are serving a .jade like always, and then, you include the vue library to use it.
Later, you can approach a better front-end development using Gulp and Webpack-Stream tools to compile .vue files.
A gulpfile.js like this, to compile all scripts of your app:
gulp.task('scripts', () => {
return gulp.src("resources/assets/js/main.js")
.pipe(named())
.pipe(webpack(require('./webpack.config')))
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(through.obj(function (file, enc, cb) {
// Dont pipe through any source map files as it will be handled
// by gulp-sourcemaps
var isSourceMap = /\.map$/.test(file.path);
if (!isSourceMap) this.push(file);
cb();
}))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest("./public/js"))
.pipe(notify("Scripts compiled"));
});
The content of your webpack.config.js could be:
module.exports = {
devtool: 'source-map',
module: {
loaders: [
{ test: /\.vue/, loader: 'vue' },
],
},
};
*Note that you will need the vue-loader package to let Webpack compile .vue files
By this way you will be able to develop a complete Express & Jade + VueJS application.
I hope it helps.
You need to compile jade file into HTML. I used prepros for compiling. But I already transfer to haml instead of jade. But this will work perfectly.
for inline javascript. Use this
script.
if(usingJade)
console.log('you are awesome')
else
console.log('you are not awesome');
In general case - using of webpack is already enough for goal.
I have similar case before with entry jade template and .vue files. Based on this example
I'm making a chrome extension that hosts multiple applications (multiple devtools panels), each one independent. I need webpack to watch multiple entry points and produce multiple bundles, I don't need common chunks. I definitely do not want to use amd in the client side code like this.
/appOne
index.js
/components
/blah
/foobar
/appTwo
index.js
/components
..etc
/appThree
index.js
/components
..etc.
/chrome <- basically the "dist" folder
/appOne
index.html
bundle.js
/appTwo
index.html
bundle.js
/appThree
etc...
As per docs on multiple entries I've been doing:
{
entry: {
appOne: './appOne/index.js',
appTwo: './appTwo/index.js'
},
output: {
path: path.join(__dirname, 'chrome', '[name]'),
filename: 'bundle.js' //can be the same since they should be output in different folders
}
}
I get the error:
Path variable [name] not implemented in this context: C:\Users\Admin\projects\crx\chrome\[name]
So I guess you cannot have the [name] variable in the path setting for multiple entries?
You should use [name] in the filename field instead of path. Looking at the docs, filename lists the [name] variable and path does not (only showing [hash]).
You would use something like:
{
path: path.join(__dirname, 'chrome'),
filename: '[name]/bundle.js'
}
The documentation does not explicitly state the filename can have multiple path segments, it only says the filename must not be an absolute path.
So, I'm moving from grunt to gulp (or trying to anyway), and I'm having trouble getting gulp to do what I'm doing in grunt. Specifically the $templateCache stuff.
My angular app is broken up into several components/modules. Each module contains everything it needs to run (controllers, directives, partials, scss, etc.).
Using Grunt, I've been able to boil each module down into 5 files:
module.min.css // all module scss files compiled and concatenated
module.min.js // all module controllers, directives, services, etc. concatenated
module.tpls.min.js // all partials in $templateCache for this module
module.mocks.min.js // all unit test mock objects for this module
module.specs.min.js // all unit test specs for this module
This has worked really well for 2 years now and been a cornerstone of my modular architecture. My only reasons to try out gulp was 1) Curiosity, 2) My grunt file is getting kinda hairy as we add in deployment and environment specific stuff and so far gulp has really slimmed that down.
For the most part, I've figured out how to do all my grunt tasks in gulp, but I'm having trouble figuring out how to generate a template cache file for each module. All the gulp-ng|angular-templates|templatecache plugins take all my partials and create one file. I'd like to take all my files under module/partials/*.html and create a single module.tpls.min.js; and do that for each module.
This was actually a problem with grunt too, but I figured it out with grunt.file.expand().forEach() like this:
grunt.registerTask('prepModules', '...', function(){
// loop through our modules directory and create subtasks
// for each module, modifying tasks that affect modules.
grunt.file.expand("src/js/modules/*").forEach(function (dir) {
// get the module name by looking at the directory we're in
var mName = dir.substr(dir.lastIndexOf('/') + 1);
// add ngtemplate subtasks for each module, turning
// all module partials into $templateCache objects
ngtemplates[mName] = {
module: mName,
src: dir + "/partials/**/*.html",
dest: 'dev/modules/' + mName + '/' + mName + '.tpls.min.js'
};
grunt.config.set('ngtemplates', ngtemplates);
});
});
My current gulp for this same task:
var compileTemplates = gulp.src('./src/js/modules/**/partials/*.html', {base:'.'})
.pipe(ngTemplates())
.pipe(gulp.dest('.'));
I've only really looked at the options, but none of them seemed to do what I wanted. They were all around changing the file name, or the final destination of the file, or a module name, or whatever else; nothing that said anything about doing it for only the directory it happens to be in.
I had thought about using gulp-rename because it worked well for me when doing the CSS compilation:
var compileScss = gulp.src('./src/js/modules/**/scss/*.scss', {base:'.'})
.pipe(sass({includePaths: ['./src/scss']}))
.pipe(rename(function(path){
path.dirname = path.dirname.replace(/scss/,'css');
}))
.pipe(gulp.dest('.'));
However, when I pipe rename() after doing ngTemplates() it only has the path of the final output file (one log entry). When you console.log() path after sass(), it has all the paths of all the files that it found (lots of log entries).
Any ideas? Thanks!
This SO post has the correct answer, but the wasn't coming up in my searches for this specific usage. I was going to vote to close my question, but since someone else might search using my own specific terms (since I did), it seems more appropriate to leave it alone and just redirect to the original question as well as show how I solved my own particular problem.
var fs = require('fs');
var ngTemplates = require('gulp-ng-templates');
var rename = require('gulp-rename');
var modulesDir = './src/js/modules/';
var getModules = function(dir){
return fs.readdirSync(dir)
.filter(function(file){
return fs.statSync(path.join(dir, file)).isDirectory();
});
};
gulp.task('default', function(){
var modules = getModules(modulesDir);
var moduleTasks = modules.map(function(folder){
// get all partials for this module
// parse into $templateCache file
// rename to be /dev/modules/_____/______.tpls.min.js
return gulp.src(modulesDir + folder + '/partials/*.html', {basedir:'.'})
.pipe(ngTemplates({module:folder}))
.pipe(rename(function(path){
path.dirname = './dev/apps/' + folder + '/';
path.basename = folder + '.tpls.min';
}))
.pipe(gulp.dest('.'));
});
});
It's essentially like the tasks per folder recipe but with a change to use gulp-ng-templates. I'll probably be using this same pattern for my SCSS and JS now that I'm more aware of it.
Seems like the gulp equivalent of grunt.file.expand().forEach().
Whenever I deal with scss/sass for gulp tasks, I will only put one scss file as the source parameter. This parameter file is composed of a list of imports. This way you don't need to rely on gulp to concat the scss file contents for you.
//in gulpfile
gulp.src('./src/js/modules/**/scss/main.scss', {base:'.'})
//in main.scss
#import 'a', 'b', 'c';
a, b, and c would represent your other scss files.
I am trying to export a module to my routes file.
My file tree goes like
routes.js
app.js
controllers/users.js
posts.js
on my app.js I exported var route = require('./routes'); and that works.
now on my routes.js I tried to export require('./controllers');.
But it keeps telling me that it cannot find module controllers.
Doing this works:
require('./controllers/users')
But I am trying to follow expressjs sample initial projects format.
And it is bugging me because the example of expressjs shows: (express routes is a folder)
var routes = require('./routes');
and loads it like
app.get('/', routes.index);
with no error. and that ./routes is a folder. I am just following the same principle.
If you try to require a directory, it expects there to be an index.js file in that directory. Otherwise, you have to simply require individual files: require('./controllers/users'). Alternatively, you can create an index.js file in the controllers directory and add the following:
module.exports.users = require('./users');
module.exports.posts = require('./posts');
and then import: var c = require('./controllers');. You can then use them via c.users and c.posts.
You have to understand how require() works.
In your case it fails to find a file named controller.js so it assumes it's a directory and then searches for index.js specifically. That is why it works in the express example.
For your usecase you can do something like this -
var controllerPath = __dirname + '/controllers';
fs.readdirSync(controllerPath).forEach(function(file) {
require(controllerPath + '/' + file);
});
From:
http://nodejs.org/api/modules.html
LOAD_AS_DIRECTORY(X)
If X/package.json is a file, a. Parse X/package.json, and look for "main" field. b. let M = X + (json main field) c.
LOAD_AS_FILE(M)
If X/index.js is a file, load X/index.js as JavaScript text. STOP
If X/index.node is a file, load X/index.node as binary addon. STOP
So, if a directory has an index.js, it will load that.
Now, look # expressjs
http://expressjs.com/guide.html
create : myapp/routes
create : myapp/routes/index.js
Taking some time to really read how modules work is time well spent. Read here