Ember-CLI: How to exclude a folder within /public from build - ember-cli

I have Ember-CLI-application with a few thousand static assets (~1GB) and my build time is now about 30sec.
I have tried in my Brocfile.js without success:
var app = new EmberApp({
fingerprint: {
enabled: false,
exclude: ['large_folder']
}
});
Build time with assets: TreeMerger | 29738ms
/ without: TreeMerger | 9182ms.
Any ideas how to speed up the build?
(Ember-CLI 0.1.7)

You have enabled:false, you can set it to true.
Also, on exclude, would be better to say the path for the folder, such as:
If you have a large folder inside images, then you can do it like this:
fingerprint: {
exclude: ['assets/images/large_folder/', 'assets/uploads/other_large_folder/]
}

My own solution is currently to use the postBuild-hook and a symbolic link to the assets folder.
lib/link-after-build/index.js:
var fs = require('fs');
var path = require('path');
module.exports = {
name: 'link-after-build',
// link additional assets after build
postBuild: function(result) {
if (process.env.EMBER_ENV === 'development') {
var buildDirPath = result.directory;
var srcpath = path.resolve("/opt/local/apache2/htdocs/large_folder");
var dstpath = path.resolve(buildDirPath + "/large_folder");
fs.symlinkSync(srcpath,dstpath);
}
}
};

Related

How we can generate html report in cucumber latest version(3.2.0) with protractor-cucumber framework

Since cucumber 3 removed the registerHandler and registerListener , how we can generate html report in cucumber 3.2.0.I have used below code for generating json report in cucumber 2.
defineSupportCode(function({ registerListener }) {
var JsonFormatter = new Cucumber.JsonFormatter();
JsonFormatter.log = function(string) {
var outputDir = 'testreports/report';
var fileName = 'cucumber-report.json';
var targetJson = path.resolve(outputDir, fileName);
if (fse.existsSync(outputDir)) {
fse.moveSync(outputDir, outputDir + '_' + moment().format('YYYYMMDD_HHmmss'), {
overwrite: true
});
}
fse.outputFileSync(targetJson, string);
};
registerListener(JsonFormatter);
});
and used below code for html report
defineSupportCode(function({ registerHandler }) {
registerHandler('AfterFeatures', function(features, callback) {
var options = {
theme: 'bootstrap',
jsonFile: 'testreports/report/cucumber-report.json',
output: 'testreports/report/cucumber-report.html',
reportSuiteAsScenarios: true,
};
reporter.generate(options);
callback();
});
});
Thanks in advance.
You have to do following changes:
1) set cucumberOpts.format in protractor conf file
cucumberOpts: {
format: ["json:reports/report/cucumber/cucumber-report.json"],
here reports/report/cucumber/cucumber-report.json is the cucumber json file path, you must specify a path at here.
framework will generate it automatically with results' json data as file content when all scenarios execute complete.
2) create parent folder of cucumber json file path before test framework load if parent folder not exist
Option 1: put create parent folder code at head of protractor conf file.
Option 2: create a Protractor plugin implement interface: setup(), which will be executed before test framework load.
// plugin: create-report-folder.js
var moment = require("moment");
var fse = require("fs-extra");
module.exports = {
setup: function() {
var reportDir = this.config.options.reportDir;
if (fse.existsSync(reportDir)) {
fse.moveSync(
reportDir,
reportDir + "_" + moment().format("YYYYMMDD_HHmmss"),
{ overwrite: true}
);
}
fse.mkdirsSync(reportDir);
}
};
Note: both options need to use Sync api to create folder.
3) create Protractor plugin implement interface: postResults which will be executeed after all scenarios execute complete.
// plugin: cucumber-html-reporter.js
var reporter = require("cucumber-html-reporter");
module.exports = {
postResults: function() {
var options = {
theme: "bootstrap",
jsonFile: this.config.options.jsonFile,
output: this.config.options.htmlFile,
reportSuiteAsScenarios: true
};
reporter.generate(options);
}
};
Note: I tried generate cucumber html report in cucumber AfterAll hook, but failed, seems Cucumber JsonFormater generate cucumber json file is Async, when AfterAll hook start execute, cucumber json file have not create yet.
I'm keeping look into formatOption, should be a way to change JsonFormater generate cucumber json file to Sync, then we can use AfterAll hook.
4) set plugins in protractor conf file
// protractor conf file
exports.config = {
plugins: [
// plugin to create report parent folder
{
path: "supports/create-report-folder.js",
options: {
reportDir: "reports/report/cucumber"
}
}
// plugin to generate cucumber html report
{
path: "supports/cucumber-html-reporter.js",
options: {
jsonFile: "reports/report/cucumber/cucumber-report.json",
htmlFile: "reports/report/cucumber/cucumber-report.html"
}
}
]
A workable scaffold for Protractor + Cucumber4 + HTML Report at my github
The scaffold for Protractor + Cucumber3 + HTML Report on my local has some dependency campatible issue, I'm looking into that in case you must use Cucumber 3.
5) If you use multiCapabilities, you can use below package to generate report:
protractor-multiple-cucumber-html-reporter-plugin
If the location of protractor.conf.js is not at the same level as node_modules then the cucumberOpts.format path would be relative to its current file location and the protractor-multiple-cucumber-html-reporter-plugin looks for the json files relative to parent root folder and warns about json file is not found.
To solve this provide absolute path of the json file to cucumberOpts.format like below. This is applicable if you're using cucumber for e2e testing in Angular applications where the protractor.conf.js is normally present inside e2e folder.
cucumberOpts: {
require: [path.resolve(process.cwd(), 'e2e/steps/*.ts')],
format: 'json:'+ path.resolve(process.cwd() + '/reports/cucumber-ui-reports.json')
}

How to move/copy files during ember build

I wanted to moved some files between two folders in an ember app when build is run but I am having no success.
//ember-cli-build.js
module.exports = function (defaults) {
var app = new EmberApp(defaults, {
hinting: false,
minifyCSS: {
enabled: true
},
bless: {
enabled: true
}
});
var moveFile = new Funnel('./app/locales', {
srcDir: 'en',
files: ['test.js'],
destDir: 'en_US',
allowEmpty: true
});
return new MergeTrees([moveFile, app.toTree()]);
};
When I do the build, I get no errors but the file is also not getting moved.
UPDATE: I am trying to move the file before ember-cli puts compiles the files and puts it in the dist folder
You can use broccoli-static-compiler https://github.com/joliss/broccoli-static-compiler
In brocfile.js ( ember-cli-build.js )
// at top of file
var pickFiles = require('broccoli-static-compiler');
var mergeTrees = require('broccoli-merge-trees');
// inside exporting function
const bootstrapMap = pickFiles('bower_components/bootstrap/dist/css/',
{
srcDir: '/',
files: ['bootstrap.css.map'],
destDir: '/assets'
});
// and so on, as many times as you need
const zeroClipboard = pickFiles('bower_components/zeroclipboard/dist/',
{
srcDir: '/',
files: ['ZeroClipboard.swf'],
destDir: '/assets'
});
// at the end
return mergeTrees([
app.toTree(),
bootstrapMap,
zeroClipboard,
// ...
], { overwrite: true });
With 'broccoli build', your app is build into a destination folder, so broccoli is the wrong tool to move files in an existing folder structure. Here I'm assuming it's run with something like 'broccoli build dist' on the command line which will create a new folder 'dist' with the results of the build, and error out if the directory already exists.
So let's say your project directory looks like this:
.
|--brocfile.js
|--app/
|--locales/ <----- funnel root
|--en/ <----- srcDir
|--test.js <----- file
When you funnel from ./app/locales, your srcDir and files` are relative to that as a root. The output tree is then put into the 'destDir' under the build output directory. What that will do is this:
.
|--brocfile.js
|--app/ <----- not changed
|--dist/ <----- build output directory
|--en_US <----- destDir
|--test.js <----- file
I think you want your destDir to be locales/en_US or app/locales/en_US.

Why is gulp-rsync not deploying?

Im trying to deploy to a staging site with gulp-rsync. I'm not receiving any errors but it's not deploying to My server. I would also expect to be asked for the password, which is not happening.
var gulp = require('gulp'),
gutil = require('gulp-util'),
sass = require('gulp-sass'),
autoprefixer = require('gulp-autoprefixer'),
minifycss = require('gulp-minify-css'),
jshint = require('gulp-jshint'),
stylish = require('jshint-stylish'),
uglify = require('gulp-uglify'),
concat = require('gulp-concat'),
rename = require('gulp-rename'),
plumber = require('gulp-plumber'),
bower = require('gulp-bower'),
sftp = require('gulp-sftp'),
rsync = require('gulp-rsync');
gulp.task('deploy', function() {
gulp.src('build/test_for_rsync')
.pipe(rsync({
root: 'build',
hostname: '*****.wpengine.com',
username: '*****',
port: 2222,
destination: '/wp-content/themes/',
incremental: true,
progress: true,
relative: true,
exclude: ['/node_modules', '/bower_components'],
recursive: true
}));
});
Try using return keyword before gulp.src:
gulp.task('deploy', function() {
return gulp.src('build/test_for_rsync')
.pipe(rsync({
root: 'build', ...

How to serve a static folder in sails.js?

I want to serve a folder app, which is at the same level with assets folder, under the url /app.
It's possible with AppController to serve file according the url, but I want to know whether it is possible to do this like the following with express?
app.use(express.static(__dirname + '/public'));
You can use custom middleware for express in sails by adding it to your config/http.js:
var express = require('express');
module.exports.express = {
customMiddleware: function (app) {
app.use(express.logger());
app.use(express.compress());
app.use('/app', express.static(process.cwd() + '/../client/www/'));
}
};
Off the top of my head, there's two choices:
Create a symlink assets/app pointing to your destination. The resources should be accessible via http://your.host.com/app/* since that's the way Sails serves assets.
There's still Express underneath Sails, you should be able to access it with sails.express.app and do your thing, let's say, from config/bootstrap.js:
var express = require('express');
…
sails.express.app.use(express.static(process.cwd() + '/app'));
I'm using Sails.js v0.12.4. The http.js uses module.exports.http and not module.exports.express I did the following to serve up another folder like the existing /assets folder. In my example to serve up the app folder, replace the 'node_modules/bootstrap/dist' path with /app
In the config/http.js file I added
var express = require('express');
Then in the middleware object I added the express static module. I'm wanting to serve up the bootstrap assets contained in my node_modules folder.
bootstrapAssets: express.static('node_modules/bootstrap/dist'),
Then in the order array, I added the 'bootstrapAssets' in the order I wanted this middleware to run. Here is the full code:
var express = require('express');
module.exports.http = {
middleware: {
passportInit : require('passport').initialize(),
passportSession : require('passport').session(),
bootstrapAssets : express.static('node_modules/bootstrap/dist'),
order: [
'startRequestTimer',
'cookieParser',
'session',
'bootstrapAssets',
'passportInit',
'passportSession',
'myRequestLogger',
'bodyParser',
'handleBodyParserError',
'compress',
'methodOverride',
'poweredBy',
'$custom',
'router',
'www',
'favicon',
'404',
'500'
],
Now in my HTML I can access the the bootstrap css using the following:
<link rel="stylesheet" href="/css/bootstrap.min.css">
In Sails 1.0 you can modify the file config/routes.js and add this:
var express = require('express')
var serveStatic = require('serve-static')
var os = require('os')
const dir = `${os.homedir()}/foo` // dir = /home/dimas/foo
module.exports.routes = {
'/public/*': serveStatic(dir, {skipAssets: true}), // <-- ADD THIS
'/': {
controller: 'FooController',
action: 'checkLogin'
},
};
Then you have to create the directory structure:
/home/dimas/foo/public
NOTE that the public entry (the route) is INCLUDED in the filesystem path, the files to be served must be placed there!
After that you can access any content by hitting the following URL:
http://localhost:1337/public/foratemer.txt
You can serve your files simple like this:
var express = require('../node_modules/sails/node_modules/express');
module.exports.express = {
middleware: {
custom: true
},
customMiddleware: function (app) {
app.use(express.logger());
app.use(express.compress());
app.use('/api/docs',express.static('assets/swagger-ui/dist/'));
}
};
This is my config/express.js file
You can use this for sails 0.12.3:
Install express to your sail: npm install express --save
After that, modify config/route.js
module.exports.routes = {
...
'/public/*': require('express').static('the-directory-that-contains-public-director')
...
}
This will works. However, it is a bit ugly that you have to create a directory as a parent for your public directory. It is because the static middleware create by express will count the '/public/' prefix in calculating to path to the target files.
Sails v1.0: Serve a file with a . dot folder in sails. Example: https://myWebSite.com/.well-known/test.txt
in the config/http.js file add express.static to serve and then add publicFolder in the order array.
module.exports.http = {
middleware: {
publicFolder: express.static('public/public'),
order: [
'cookieParser',
'session',
'publicFolder'
// 'favicon',
],
}}
Create a public folder and .well-known folder so public/.well-known/test.txt

How can I use grunt-regarde with grunt-contrib-coffee to only compile changed .coffee files?

My project has over 300 CoffeeScript files, so it takes several seconds to recompile everything. I'd like to only recompile the changed CoffeeScript files.
Here's the closest I've come so far, but the "frontend-src/coffeescript" folder structure is being copied from the src directory to the dest directory.
coffee: {
changed: {
expand: true,
cwd: './',
src: ['<%= grunt.regarde.changed %>'],
dest: 'public/js/',
ext: '.js'
}
},
regarde: {
coffee: {
files: 'frontend-src/coffeescript/**/*.coffee',
tasks: ['coffee:changed', 'livereload']
}
}
This is all with Grunt 0.4.0. Any help would be greatly appreciated!
I had this issue myself and I was able to come up with a solution for it inspired by the comments on this issue:
https://github.com/gruntjs/grunt-contrib-watch/issues/14
It is actually for the grunt-contrib-watch plugin, but it should also work for grunt-regarde, as it has similar events.
The idea is to bind a callback the watch event, in which you add a new task to the grunt configuration with the changed file's path, then run it.
From my Gruntfile.coffee:
coffee:
app:
expand: true
cwd: 'app/'
src: ['*.coffee',"**/*.coffee"]
dest: './public/temp'
ext: '.js'
watch:
coffee:
files: ['app/**/*.coffee']
tasks: ['livereload']
options:
nospawn: true
grunt.event.on 'watch', (action, filepath) ->
cwd = 'app/'
filepath = filepath.replace(cwd,'')
grunt.config.set('coffee',
changed:
expand: true
cwd: cwd
src: filepath
dest: './public/temp'
ext: '.js'
)
grunt.task.run('coffee:changed')
The nospawn is important for the watch task, so it runs the new task before the livereload task. I am pretty sure regarde does not spawn child processes by default.
I've had the same issue. I solved it using the regarde:file event.
First I listen for changed files by using the regarde:file event. This will feed the configuration for two tasks: clean:coffee if files in the source location has been deleted and coffee:refresh if files have been changed/added.
Then the regarde task will trigger its tasks, which will launch refresh:coffee (not to be mistaken from coffee:refresh). This task will check if there is configuration added for clean:coffee and/or for coffee:refresh and run these tasks if needed (via function grunt.task.run). If will also reset the flag, which will cause the next received regarde:file event to cleanup the configuration again.
In depth explanation:
First of all, regarde config:
// watch for changed coffeescript files
coffee: {
files: 'path/to/coffee/**/*.coffee',
tasks: ['refresh:coffee', 'livereload']
},
Then I listen for the regarde:file event, where I update the clean:coffee and coffee:refresh file lists in their config.
Feed the configuration based on the regarde:file event:
grunt.event.on('regarde:file', function (status, target, filepath) {
if (resetFlag) {
// clean file list from previous cycle, so clean clean:coffee and coffee:refresh
// file lists
...
resetFlag = false;
}
if (status === 'deleted') {
if (filepath) {
// calculate filepath's destination and
// add it to clean:coffee filelist
}
} else {
if (!grunt.file.isDir(filepath)) {
// add filepath to coffee:refresh filelist
}
}
}
It is easy to update configuration via grunt.config() function. Below the code snippets to feed coffee:refresh and clean:coffee.
Adding config to coffee:refresh:
var config = grunt.config('coffee') || {};
var value = config.refresh || {};
value.files = value.files || [];
...
var cwd = path.dirname(filepath),
src = path.basename(filepath),
dest = cwd.replace('path/to/source', 'path/to/dest');
value.files.push({
expand:true,
src:src,
dest:dest,
cwd:cwd,
ext:'.js'
});
grunt.config('coffee', config);
Adding config to clean:coffee:
var cwd = path.dirname(filepath),
src = path.basename(filepath),
dest = cwd.replace('path/to/source', 'path/to/dest');
value.src.push(path.join(dest, src.replace('coffee', 'js')));
// clean only what has been removed
config = grunt.config('clean') || {};
config.coffee = value;
grunt.config('clean', config);
Task refresh:coffee gets triggered:
grunt.registerMultiTask('refresh', 'refreshing the changed file(s)', function () {
this.requires('regarde');
var tasks = [];
var clean = grunt.config('clean');
// check if there is clean:refresh config available
if (clean && clean[this.target]) {
tasks.push('clean:' + this.target);
}
var config = grunt.config(this.target);
// check if there is coffee:refresh config available
if (config && config.refresh) {
tasks.push(this.target + ':refresh');
}
// run the tasks
grunt.task.run(tasks);
// set the resetFlag back to true
resetFlag = true;
});
grunt.regarde.changed is an array correct?
Should src: ['<%= grunt.regarde.changed %>']
be src: '<%= grunt.regarde.changed %>'
I looked through grunt-contrib-coffee's source for a second to see if it could be not correctly handling whatever you're giving it. Looked kind of likely that the stringified array you're giving it, doesn't get caught and dealt with.
I think what you're passing accidentally may be: src: [ '[path1, path2, path3, etc]' ]
If I'm way off base, leave a comment and I'll delete this answer.