How can I configure Express to render all Jade files regardless of path? The application I'm on is large with a very complex structure. I'm successfully serving static files however I need many of them to be rendered. We are using Jade for all files needing markup.
I'm worried that the pattern below will force me to create a route alias for every folder that has a Jade file... which would be bad. I would like to tell Express to simply render everything with a .jade extension... OR... allow me to create a route PREFIX for the root that would cause a Render operation instead of Static.
client
app
services
modules
moduleA
itemA
itemAList.jade
itemAList.js
itemADetails.jade
itemADetails.js
itemB
itemBList.jade
itemBList.js
itemBDetails.jade
itemBDetails.js
moduleB
itemC
itemCList.jade
itemCList.js
itemCDetails.jade
itemCDetails.js
itemD
itemDList.jade
itemDList.js
itemDDetails.jade
itemDDetails.js
assets
js
css
server
config
views
Routes.Config.js
module.exports = function(app){
app.get('/*', function(req, res){
res.render('../../client/' + req.params[0]);
});
app.get('/', function(req, res){
res.render('../../client/index', {});
})
}
Express.Config.js
[snip]
app.use(express.static(path.join(constants.rootPath, '/client')));
I would use a Grunt file watcher to kick off a compile any time your .jade files are created or saved. By using the Gruntfile.js below, you can issue the command grunt watch and have this automagically occur in the background:
module.exports = function(grunt){
grunt.initConfig({
jade: {
compile: {
options: {
client: false,
pretty: true
},
files: [{
cwd: "client/app/templates",
src: "**/*.jade",
dest: "client/app/modules",
ext: ".html",
expand: true
}]
}
},
watch: {
html: {
files: 'client/app/templates/**/*.jade',
tasks: ['jade'],
options: {
atBegin: true,
interrupt: true
}
}
}
});
grunt.loadNpmTasks("grunt-contrib-jade");
grunt.loadNpmTasks("grunt-contrib-watch");
grunt.registerTask('default', ['jade']);
}
Now, this assumes that you will create a "templates" folder parallel to the "modules" folder and put all of your .jade files there in the structure you want. You may then add your controllers and other .js files to the modules folder structure as normal.
I'm not sure how Grunt will behave with the source and destination both pointing to the same folder. However, if you REALLY want to keep your .jade and .html files in the same folder, or if you don't want to create a "templates" structure, you SHOULD be able to simply change the cwd variable to point to the "modules" folder:
files: [{
cwd: "client/app/modules", // templates folder removed
src: "**/*.jade",
dest: "client/app/modules",
ext: ".html",
expand: true
}]
NOTE:
Sounds like you've misunderstood some of the fundamentals. From what I'm learning, within a typical MEAN application, there is generally a folder structure that is meant to be purely static. In your example, this would be your "client" folder. By specifying special routes, you individually decide how every other case is handled. The example above is meant to accomplish what I think you're asking while still maintaining the purpose of the "static" area.
UPDATE: Don't use same folder!
I went back and tried using the same folder for the source and destination. This caused Grunt to hang without any way to break out of it. This hang does NOT occur when they are different. So, use the file as-is with the "templates" folder.
Related
I am newbie to service worker concept so forgive me if I am overlooking something from documentation. I have an angular application already running in production and I am trying to introduce service worker using sw-precache.
To start with I am trying to precache all images/fonts and couple of js files and see if it works, so my precache config is like this -
{
"cacheId": "static-cache",
"importScripts": [
"sw-toolbox.js"
],
"stripPrefix": "dist/",
"verbose": true,
"staticFileGlobs": [
"dist/img/**.*",
"dist/javascripts/require.js",
"dist/stylesheets/**.*",
"dist/webfonts/**.{ttf, eot, woff}",
"sw-toolbox.js",
"service-worker.js"
]
}
Now I can see service worker registered and installed properly and cache storage shows all the urls with _sw-precache hashes.
But when I load the application and see in network tab all static content are still served from memory/disk, not from service worker and I am unable to debug why is it so. Am I missing something here -
UPDATE:
More information: I had wrong configurations since I have dynamic url and server side rendered html. Server side it's test.jsp which is giving me initial shell.
For now I have removed all other static files from cache and kept only show.css
So update config now is -
{
"importScripts": [
"sw-toolbox.js"
],
"stripPrefix": "dist/",
"verbose": true,
"staticFileGlobs": [
"dist/stylesheets/show.css"
],
"dynamicUrlToDependencies": {
"/developers": ["dist/stylesheets/show.css"]
},
"navigateFallback": "/developers"
}
Web root folder is named differently and it is -
- dashboard
-- img
-- javascripts
-- service-worker.js
-- sw-toolbox.js
- test.jsp
And I see /developers url as an entry in storage cache, but still it's not served from service worker for next refresh. I have tried all my energy to fix this, but I desperately need some clue here, what's missing in here. TIA.
Let me know if need more info.
It seems that whitespaces in your file extension list are not allowed. Your definition for webfonts should be:
"dist/webfonts/**.{ttf,eot,woff}",
I cloned the sw-precache repo and added a unit test where I compared two generated files with two diffrent staticFileGlobs, one with whitespace and one without.
it('should handle multiple file extensions', function(done) {
var config = {
logger: NOOP,
staticFileGlobs: [
'test/data/one/*.{txt,rmd}'
],
stripPrefix: 'test'
};
var configPrime = {
logger: NOOP,
staticFileGlobs: [
'test/data/one/*.{txt, rmd}'
],
};
generate(config, function(error, responseString) {
assert.ifError(error);
generate(configPrime, function(error, responseStringPrime) {
assert.ifError(error);
console.log('responseStringPrime',responseString);
assert.strictEqual(responseString, responseStringPrime);
done();
});
});
});
and it failed. The second config didn't include the .rmd file:
-var precacheConfig = [["/data/one/a.rmd","0cc175b9c0f1b6a831c399e269772661"],["/data/one/a.txt","933222b19ff3e7ea5f65517ea1f7d57e"],["/data/one/c.txt","fa1f726044eed39debea9998ab700388"]];
versus
+var precacheConfig = [["test/data/one/a.txt","933222b19ff3e7ea5f65517ea1f7d57e"],["test/data/one/c.txt","fa1f726044eed39debea9998ab700388"]];
I am setting up my Karma configuration file, but I do not fully understand some of options that exist as I am not having success testing templates that have ran through the ngHtml2JsPreprocessor and have been
$templateCached
Inside of the ngHtml2JsPreprocessor I can add a few key value properties involving paths.
ngHtml2JsPreprocessor: {
stripPrefix: ".*/Went all the way back to the root of my application/",
// moduleName: 'templatesCached'//
},
I commented out the templates for now to make sure that I am getting access to each file as module. I am loading the modules with no error. I can find the templateCached version in my dev tools.
beforeEach(module('template'));
My Templates folder sits outside the basepath I created.
basePath: 'Scripts/',
I have it referenced inside the preprocessors object
preprocessors: {
'../Templates/**/*.html' : ['ng-html2js']
},
Again all of my templates are now js files and cached.
I inside of my package.json I saved the files as
save-dev
"karma-chrome-launcher": "^0.2.2",
"karma-jasmine": "^0.2.2",
"karma-ng-html2js-preprocessor": "^0.2.1",
I referenced my installs in the plugins.
plugins: [
'karma-chrome-launcher',
'karma-jasmine',
'karma-sinon',
'karma-ng-html2js-preprocessor'
],
I have all of my files loaded
files: [
//jquery libaries
// angular libraries
// Scripts files
// source app.js
// tests folder and files
]
My tests are running off of Karma start
However, my directive is just an empty string
element.html()
returns ""
I have bard inject set up
bard.inject(
"$compile",
"$controller",
"$rootScope",
'$templateCache',
"haConfig",
"$q"
);
Here is the inside of my beforeEach
bard.mockService(haConfig, {
getTemplateUrl: '/tst!'
});
//bard.mockService(haConfig, {});
console.log('ha config2', haConfig.getTemplateUrl());
var html = angular.element("<div explore-hero></div>");
console.log('htl',haConfig.getTemplateUrl());
scope = $rootScope.$new();
//templateCache
element = $compile(html)(scope);
//console.log(haConfig.getTemplateUrl(html));
scope.$digest(element);
console.log('missing text',haConfig.getTemplateUrl(html));
controller = element.scope();
console.log("element", element);
I have no idea why I am getting an empty string back. I am creating the html file but, nothing is inside of it.
All I can wonder if I should have the the templatesCached files showing up in a folder on my dev tools? Also whether or not the files should be referenced inside of the files array inside karma.conf.js
Right now I have the html files referenced? I have tried the js files but that did not seem to do anything
The problem was actually quite simple fix. I was tempted to delete it but, in case someone has a similar issue I want this to be available.
Inside the karma.conf.js I have a
stripPrefix: 'rootDirectory' // was already in place
stripSuffix: '.js.html' // I had to make a strip on the templatesCached
prependSuffix: '.html' // this is what I was searching for
When the preprocessor ran it templateCached all of my files. However, they did not end the way that I was expecting them and I could not read them. I had the module and other parts set up correctly.
So I ran into an issue when trying to use toastr as a global error notification system in my angular application.
This was logged as an issue with angular-toastr and the proposed solution was to push all templates into the templatecache. Apparently this is a good thing to do and after reading up on why, I have to agree.
My problem is that I am really new to grunt (only just installed it today) and although I have now managed to successfully set up my gruntfile.js and run some tasks (minification, concatination, etc) using grunt-angular-templates is a mystery to me.
I have set up my gruntfile like this:
ngtemplates: {
options: {
module: 'project',
},
dist: {
src: [
'wwwroot/lib/angular-toastr/**.html'
],
dest: 'wwwroot/js/templates.js'
}
}
But my templates file that is generated is empty.
I assume this is because scripts are creating in the JS files.
Does anyone know how I can get access to the them so I can add them to the cache?
I would guess that your source files are not being 'seen'. This worked for me with the following configuration and I am using a similar structure where the output is in a wwwroot/lib folder. I am also using the cwd (source directory option). Make sure that the templates are copied to the wwwroot folder before the grunt task is executed. I have other grunt tasks that 'clean' the wwwroot/lib folder so I store my source html(s) in another folder. That may also help if you are not doing that.
If all else fails, run in verbose -V (like alex said). The task source file is in the following location. You can also add additional debug in this file to further trouble shoot.
node_modules\grunt-angular-templates\tasks\angular-templates.js
this.files.forEach(function(file) {
if (!file.src.length) {
grunt.log.warn('No templates found');
}
This is the setup we use.
Project structure
Source
project/assets/templates/admin/partials/(html files here)
Output
project/wwwroot/lib/templates(html files here)
Grunt Task
ngtemplates: {
app: {
cwd: 'assets/templates',
src: '**/partials/*.html',
dest: 'assets/templates/partials.js',
options: {
module: 'cms.admin'
}
}
},
The Output Generates
angular.module('cms.admin').run(['$templateCache', function($templateCache) {
'use strict';
$templateCache.put('Admin/partials/navmenu.template.html',
"<nav class=\"navbar navbar-default navbar-fixed-top\">\r" +
"</nav>"
);
}]);
Your problem probably lies with your src: wwwroot/lib/angular-toastr/**.html
Maybe try using this grunt plugin, it's easy to use and does the same thing.
https://github.com/karlgoldstein/grunt-html2js
grunt.initConfig({
html2js: {
options: {
// custom options, see below
},
main: {
src: ['src/**/*.tpl.html'],
dest: 'tmp/templates.js'
},
},
})
Try running the task individually like this: grunt ngtemplates -v. The -v argument stands for verbose mode. You should get the filenames that have been read. If there are no files being read, you might have a file path problem.
For simplicity or to avoid the rabbit whole, you can also manually push the template to the cache so you can test the toastr issue.
Go to http://www.accessify.com/tools-and-wizards/developer-tools/html-javascript-convertor/
Convert the html to javascript
Use the output in the following code to cache manually.
var strVar = "";
strVar += "";
strVar += "<div class=\" container-fluid wrapper-md\">";
strVar += " <h3>Title<\/h3>";
strVar += " <div id=\"markupArea\"> <\/div>";
strVar += " ";
strVar += "<\/div>";
strVar += "";
angular.module('cms.admin').run(['$templateCache', function($templateCache) {
'use strict';
$templateCache.put('<CacheKEy>',strVar );
}]);
I am using AngularJs ui-grid http://ui-grid.info/.
While implementing, I get something which you can see in the following img in right corner of the cell instead of dropdown symbols.
Which files to include to solve this bug?
You need to download the font files:
ui-grid.woff
ui-grid.eot
ui-grid.svg
ui-grid.ttf
from here. And move them where your ui-grid.min.css lives.
Please include ui-grid CSS file by this way
<link rel="stylesheet" href="/release/ui-grid-unstable.css">
and ommit the script tag from the Authors Tutorial or Api
<script src="/release/ui-grid-unstable.css"></script>
for eg (http://ui-grid.info/docs/#/tutorial/102_sorting)
I would just like to add this answer (stolen verbatim from panciz) for the folks using Grunt who would like to have these automatically copied. This needs to be placed in your Gruntfile.js:
copy: {
dist: {
files: [
...
//font di ui grid
{
expand: true,
flatten: true,
dest: 'dist/styles/',
src: ['bower_components/angular-ui-grid/ui-grid.ttf',
'bower_components/angular-ui-grid/ui-grid.woff',
'bower_components/angular-ui-grid/ui-grid.eot',
'bower_components/angular-ui-grid/ui-grid.svg'
]
}
]},
You may also want to look at a recently added tutorial: http://ui-grid.info/docs/#/tutorial/116_fonts_and_installation
This covers how to install the fonts correctly, and a little bit of trouble shooting.
Another way to solve the issue is modify the CSS class as follows
.ui-grid-icon-down-dir:before {
content: '\25bc';
}
.ui-grid-icon-up-dir:before {
content: '\25b2';
}
.ui-grid-selection-row-header-buttons.ui-grid-row-selected:before{
content:'\2714' !important;
}
.ui-grid-all-selected:before{
content:'\2714' !important;
}
Try to include in your project :
<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/angular-ui/bower-ui-grid/master/ui-grid.min.css">
<script src="https://cdn.rawgit.com/angular-ui/bower-ui-grid/master/ui-grid.min.js"></script>
If you are using gulp, add this task.
gulp.task('styles', function() {
// Copy font files needed for angular-ui-grid
gulp.src(['bower_components/angular-ui-grid/ui-grid.ttf',
'bower_components/angular-ui-grid/ui-grid.woff',
'bower_components/angular-ui-grid/ui-grid.eot',
'bower_components/angular-ui-grid/ui-grid.svg'
])
.pipe(gulp.dest('dist/styles/'))
// Other style tasks here
});
{
expand: true,
cwd: 'bower_components/angular-ui-grid',
src: ['.eot', '.svg', '.ttf', '.woff'],
dest: '<%= yeoman.dist %>/styles'
}
add this code to grunt file at copy: {
dist: {
If you use ui-grid - v4.6.6, you need to put ui-grid.ttf and ui-grid.woff into folder fonts. So the structure of directory will looks like this:
ui-grid.min.css
fonts # <-- this is a folder
ui-grid.ttf # <-- in fonts folder
ui-grid.woff # <-- in fonts folder
Adding this answer to hopefully save someone a headache. I had this problem and went through all the steps I could find. However, the problem wasn't file location, etc, my issue is the .woff file was corrupted. I downloaded the fonts to my local machine and ftp'd them to the server. Unfortunately, the .woff on the server ended up in a bad state and was bombing the #font-face declaration. Although this particular problem doesn't mention any console warnings/errors, they will match issues resolved by adding the fonts to grunt/gulp/etc.
I don't recall the error in Chrome, but in Firefox it was:
downloadable font: rejected by sanitizer
So, if you've gone through the hoops and nothing seems to work, check if the font files are correct because my FTP failed for .woff and it resulted in the same Korean characters, etc.
I worked along the following tutorial to try to optimize my project into one single .js file, but unfortunately I can't seem to get the expected results. I get r.js to create an optimized folder for me, but instead of a single file, I get uglified copies of each individual .js file in their respective folders. Seems like that last concatenation step is somehow missing.
I'm trying to leverage an existing config file instead of using paths, I don't know if that specific step is breaking it.
My build/app.build.js is:
({
appDir: '../',
baseUrl: 'js',
mainConfigFile: '../js/config.js',
dir: '../../my-app-build',
modules: [{
name: 'main'
}]
})
My main.js file has the config file as its dependency:
require(["config"], function() {
require(['underscore', [...]
[...]
}
}
And the config file is where all of my project dependencies are declared:
require.config({
baseUrl: "js",
paths: {[...]},
shim: {...]},
});
Does anyone have insight into why I might not be getting that single file output that I'm looking for? I tried the other approach in this post, but that only ever produces main.js for me with the config file prepended to it.
Thanks!
The issue was caused by the following option missing from the r.js build configuration file:
findNestedDependencies: true
Without it, r.js would not go past the first require in main.js, thus loading only config.js and none of the next level of dependencies. Just for reference (note that it saves the product of optimization in the same source folder, which is not ideal) looks like this:
({
baseUrl: '.',
mainConfigFile: 'config.js',
name: 'main',
out: 'main-build.js',
findNestedDependencies: true,
})
I had the same problem and got the solution from the Github Issue list. May be this configuration parameters will help you too
https://github.com/jrburke/r.js/issues/379
If you only want one JS file built, instead of using dir: use out: for a single JS file build.
Specify output filepath:
({
// ...
out: '../main.min.js'
})