Aurelia and System.js production build - javascript

I am maintaining an existing Aurelia project that apparently wasn't created with Aurelia CLI.
I need to create a production build but am not being able with the current configuration. The development build works just fine, but, as expected, downloads a lot of code to user machine.
After running gulp prod (gulpfile listed below), I get two JS files: app-build-{revnumber}.js and vendor-build-{revnumber}.js, but Aurelia keeps trying to load the main.js file.
I tried building the main.js together (commented code in gulpfile.js), but had no success - only vendor bundle is loaded:
Here are my config files:
config.js
System.config({
baseURL: "/www",
defaultJSExtensions: true,
transpiler: "babel",
babelOptions: {
"stage": 0,
"optional": [
"runtime",
"optimisation.modules.system"
]
},
paths: {
"*": "src/*",
"github:*": "jspm_packages/github/*",
"npm:*": "jspm_packages/npm/*"
},
map: { /* mappings */ }
});
gulpfile.js
var gulp = require('gulp');
var bundler = require('aurelia-bundler');
var image = image = require('gulp-image');
var replace = require('gulp-replace');
var gulpsync = require('gulp-sync')(gulp);
var config = {
force: true,
baseURL: '.',
configPath: './config.js',
bundles: {
// "dist/main": {
// includes: [
// '[main.js]'
// ],
// options: {
// inject: true,
// minify: false,
// rev: false
// }
// },
"dist/app-build": {
includes: [
'[**/*.js]',
'**/*.html!text',
'**/*.css!text'
],
options: {
inject: true,
minify: true,
rev: true
}
},
"dist/vendor-build": {
includes: [ /* all external modules */ ],
options: {
inject: true,
minify: true,
rev: true
}
}
}
};
gulp.task("bundle", function () {
return bundler.bundle(config)
.then(function () {
gulp.src('config.js')
.pipe(replace('dist/', ''))
.pipe(replace('src', 'dist'))
.pipe(gulp.dest(''));
});
});
gulp.task("unbundle",
function () {
return bundler.unbundle(config)
.then(function () {
gulp.src('config.js')
.pipe(replace('dist', 'src'))
.pipe(gulp.dest(''));
});
});
gulp.task("image-bundle",
function () {
gulp.src('./src/media/*')
.pipe(image())
.pipe(gulp.dest('./dist/media'));
});
gulp.task("files-bundle", function () {
return gulp
.src('./src/style/material.woff2')
.pipe(gulp.dest('./dist/style'));
});
gulp.task('prod', gulpsync.sync(['unbundle', 'bundle', 'image-bundle', 'files-bundle']));
gulp.task('dev', gulpsync.sync(['unbundle']));
index.html
<!DOCTYPE html>
<html>
<head>...</head>
<body aurelia-app="main">
<script src="www/jspm_packages/system.js"></script>
<script src="www/config.js"></script>
<script>
System.import('aurelia-bootstrapper');
</script>
</body>
</html>

After a lot of little adjustments, I solved the main.js issue.
It seems like System.js looks for the dependency in the bundle and, if not found, it hits the network. Here's what I did to fix my bundle:
Consolidated dist/ folder as the bundle source
In config.js, set the path of * to dist/* and don't modify it in any Gulp task.
Before the bundle task runs, I copy all contents from src/ to dist/
In the dist/app-build bundle, I added the option depCache: true. It does not work when false (gives the error of main.js not found), but I don't really know why.
The added/modified Gulp tasks:
// deletes all files in the output path
gulp.task('clean', ['unbundle'], function () {
return gulp.src(['dist/'])
.pipe(vinylPaths(del));
});
gulp.task('copy', function () {
return gulp.src(['src/**/*'])
.pipe(gulpCopy('dist/', { prefix: 1 }));
});
gulp.task("bundle", sync(['clean', 'copy']), function () {
return bundler.bundle(config);
});
gulp.task("unbundle", function () {
return bundler.unbundle(config);
});

Related

Babel Brunch doesn't seems to compile #polymer/lit-element module

I'm trying to integrate Lit-element into brunch. However, it seems like Babel plugin doesn't try to compile the lit-element module into the output, as it still use the original ES6 syntax of import / export.
Here's my brunch config :
`
exports.config = {
// See http://brunch.io/#documentation for docs.
files: {
javascripts: {
// joinTo: 'js/app.js'
joinTo: {
'js/app.js': [
/^node_modules/,
/\app.js$/
],
'js/editor.js': [
/\editor.js$/
],
'js/select.js': [
/select.js$/,
]
}
},
stylesheets: {
joinTo: 'css/app.css',
order: {
after: ['../priv/static/css/app.scss'] // concat app.css last
}
},
templates: {
joinTo: 'js/app.js'
}
},
conventions: {
// This option sets where we should place non-css and non-js assets in.
// By default, we set this to '/web/static/assets'. Files in this directory
// will be copied to `paths.public`, which is 'priv/static' by default.
assets: /^(web\/static\/assets)/
},
// Phoenix paths configuration
paths: {
// Dependencies and current project directories to watch
watched: [
'static', 'css', 'js', 'vendor'
],
// Where to compile files to
public: '../priv/static'
},
// Configure your plugins
plugins: {
babel: {
// Do not use ES6 compiler in vendor code
},
sass: {
mode: 'native'
},
uglify: {
mangle: false,
compress: {
global_defs: {
DEBUG: false
}
}
}
},
modules: {
autoRequire: {
"js/app.js": ["js/app"]
}
},
npm: {
enabled: true
}
}
Here is my app.js code
import {LitElement, html} from '#polymer/lit-element'
function autoComplete(options){ ... }
export var App = {
autoComplete
}
And last is the compiled code, along with console log :
...
require.register("#polymer/lit-element/lit-element.js", function(exports, require, module) {
require = __makeRelativeRequire(require, {}, "#polymer/lit-element");
(function() {
import { PropertiesMixin } from '#polymer/polymer/lib/mixins/properties-mixin.js';
// "Uncaught SyntaxError: Unexpected token {" on above line
import { camelToDashCase } from '#polymer/polymer/lib/utils/case-map.js';
import { render } from 'lit-html/lib/shady-render.js';
export { html, svg } from 'lit-html/lib/lit-extended.js';
...

The generated AMD file is not including required files inside anonymous function and pollute the global namespace

The generated AMD file is not including required files inside anonymous function and pollute the global namespace
I got Uncaught ReferenceError: define is not defined
The generated js file https://dadasay.com/plugin/v1/js/dadasay.min.js is not including required files require.js
The js file generated by runninggulp minify_plugin_js
However, the expected export js file should be like this https://gist.github.com/anonymous/32894a4065ce338fb0416f4eb2b884dd
How could I do that in Gulp js and require.js
require.js config
'use strict';
var vendor_paths = {
require: './vendor/require',
jquery: './vendor/js/jquery-2.1.1.min',
...
}
require.config({
paths: vendor_paths,
hbs: { // optional
helpers: true, // default: true
templateExtension: 'hbs', // default: 'hbs'
partialsUrl: '' // default: ''
},
shim: {
handlebars: {
exports: 'Handlebars'
},
backbone: {
deps: [
'jquery',
'underscore'
],
exports: 'Backbone'
},
underscore: {
exports: '_'
}
},
});
require(["app"],function(App){
define(["app"], function (App) {
$("#dadasay_comments_plugin").hide();
$('head').append('<link rel="stylesheet" href='+cfg.css_style_link+' type="text/css" />');
return App.initialize();
});
});
Gulp config
var v1_assets = {
css: ['public/plugin/v1/css/*.css'],
js: ['public/plugin/v1/src/**/*.js'],
require_manifest_file: "public/plugin/v1/src/main.js"
}
gulp.task('minify_plugin_js',function(){
gulp.src(v1_assets.js)
.pipe(amdOptimize("main",{
configFile: v1_assets.require_manifest_file,
findNestedDependencies: true,
include: true
}))
.pipe(concatFile('dadasay.min.js'))
})
Exported js min file
https://dadasay.com/plugin/v1/js/dadasay.min.js
define('app_config', [], function () {
return {
server_host: SERVER_HOST,
hideCommentsThreshouldNumber: 3,
comments_req_prefix: SERVER_HOST + '/api/v1/comments/load?og_url=',
css_style_link: [
SERVER_HOST,
PLUGIN_LOCATION,
'style.min.css'
].join('/')
};
});
....
The line:
define(["app"], function (App) {
is unnecessary. You required your application asynchronously already.
I believe that you could try to use the requirejs optimizer directly within gulp instead, here's how my build task looks like:
"use strict";
const requirejs = require("requirejs");
const path = require("path");
const _ = require("underscore");
module.exports = function (options, callback) {
// RequireJS Optimizer Build Configuration
// See this: https://github.com/jrburke/r.js/blob/master/build/example.build.js
// as an example file that details all of the allowed optimizer configuration options.
var buildConfig = {
appDir: options.dest,
baseUrl: "./",
optimize: "uglify2",
optimizeCss: "standard",
findNestedDependencies: true,
dir: options.build,
removeCombined: true,
fileExclusionRegExp: options.exclude || /test/,
modules: options.modules || [{
name: "runner"
}],
allowSourceOverwrites: true
};
var config = path.join(__dirname + "/../../", options.config);
var requireConfig = require(config);
_.extend(buildConfig, requireConfig);
requirejs.optimize(buildConfig, function (text) {
callback(null, text);
}, callback);
};
And then later in gulp:
const gulp = require("gulp");
const build = require("../task/build.task");
gulp.task("build", function (callback) {
build({ some: "options" }, callback);
});

getting grunt-istanbul error: No coverage information was collected

I've built a grunt setup for testing using qunit and generating coverage reports with istanbul but I can't get the storeCoverage task to complete without the error: No coverage information was collected.
Gruntfile.js
module.exports = function (grunt)
{
"use strict";
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
connect: {
root_server: {
options: {
port: 2424,
base: 'qunit'
},
}
},
qunit: {
all: ['qunit/test1.html']
},
instrument: {
files: "testable.js",
options: {
lazy: true,
basePath: "qunit/"
}
},
storeCoverage: {
options: {
dir: "report/"
}
},
makeReport: {
src: "report/*.json",
options: {
type: "lcov",
dir: "test",
print: "detail"
}
}
});
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks("grunt-contrib-qunit");
grunt.loadNpmTasks("grunt-istanbul");
grunt.registerTask("default", ["instrument", "connect", "qunit", "storeCoverage"/*, "makeReport"*/]);
};
testable.js
function runable ()
{
return true;
};
test1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>QUnit Example</title>
<link rel="stylesheet" href="qunit.css">
</head>
<body>
<script src="qunit.js"></script>
<script src="testable.js"></script>
<script>
QUnit.test("hello test", function (assert)
{
assert.ok(runable());
});
</script>
</body>
</html>
Everything works, qunit runs and the one assert does run on the instrumented file and succeeds. But when it hits the storeCoverage task it fails. Am I doing something wrong? Any help is appreciated of course.
I was able to get this working using the Gruntfile.js from the grunt-istanbul project.
Their documentation indicates that the reloadTasks is not required, but for me it actually was. The clean task they do also assists to tidy up. Also noted in their docs, you can set an ENV variable, rather than using the env task.
Try adding these to your Gruntfile.js:
env: {
coverage: {
APP_DIR_FOR_CODE_COVERAGE: rootPath + 'path/to/instrument'
}
},
clean: ['path/to/coverage'],
reloadTasks: {
rootPath: 'path/to/instrument'
},
My task looks like this:
grunt.registerTask('cover',[
'env:coverage',
'clean',
'instrument',
'reloadTasks',
'connect',
'qunit',
'storeCoverage',
'makeReport'
]);
The question is a little old, but it might help someone else.
To solve this issue, I needed to point my test code to the instrumented code otherwise the original one.
See the example:
Gruntfile.js:
module.exports = function (grunt) {
grunt.initConfig({
env: {
coverage: {
APP_DIR_FOR_CODE_COVERAGE: '../test/coverage/instrument/lib/'
}
},
clean: {
coverage: {
src: ['test/coverage/']
}
},
instrument: {
files: 'lib/*.js',
options: {
lazy: true,
basePath: 'test/coverage/instrument/'
}
},
mochaTest: {
test: {
options: {
reporter: 'spec'
},
src: ['test/**/*test.js']
}
},
storeCoverage: {
options: {
dir: 'test/coverage/reports'
}
},
makeReport: {
src: 'test/coverage/reports/**/*.json',
options: {
type: 'lcov',
dir: 'test/coverage/reports',
print: 'detail'
}
}
});
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-mocha-test');
grunt.loadNpmTasks('grunt-istanbul');
grunt.loadNpmTasks('grunt-env');
grunt.registerTask('test', 'mochaTest');
grunt.registerTask('coverage', ['env:coverage', 'clean', 'instrument', 'mochaTest', 'storeCoverage', 'makeReport']);};
In you test code, point to the instrumented ones.
As described in the grunt-istanbul site, you can create a requireHelper file.
module.exports = function (path) {
return require((process.env.APP_DIR_FOR_CODE_COVERAGE || '../lib/') + path);
};
And use it in your test file.
var requireHelper = require('./require_helper');
var fileToBeTested = requireHelper('file-to-be-tested');
describe('Test', function () {
it('should do some test', function () {
expect(1).to.equal(1);
});
});

requirejs throws a 404 trying to load a file from karma runner

I am trying to load a test helper module using requirejs, but it fails even when it has been already loaded as a dependency at the start of karma run, and I can't figure out what's the problem, I always get
There is no timestamp for /base/spec/helpers/testHelpers!'
Tests run fine, inside them I require any module of the app without problem, it only fails when I require specifically something from spec folder.
I have checked all karma related questions and none of them apply to these case.
My karma.conf file:
module.exports = function (config) {
'use strict';
config.set({
basePath: '',
frameworks: ['jasmine', 'requirejs'],
files: [
'bootstrapTests.js',
{
pattern: 'app/**/*.js',
included: false
},
{
pattern: 'entities/**/*.js',
included: false
},
{
pattern: 'config/**/*.js',
included: false
},
{
pattern: 'libs/**/*.js',
included: false
},
{
pattern: 'spec/**/*Spec.js',
included: false
},
{
pattern: 'spec/helpers/**/*.js',
included: false
}
],
exclude: [
'bootstrap.js',
'bootstrap.built.js'
],
preprocessors: {
'app/**/*.js': ['coverage'],
'entities/**/*.js': ['coverage']
},
coverageReporter: {
reporters: [
{
type: 'text-summary'
}
]
},
reporters: ['progress', 'coverage'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['PhantomJS'],
singleRun: false
});
};
My bootstrapTests.js file:
var tests = [];
for (var file in window.__karma__.files) {
if (window.__karma__.files.hasOwnProperty(file)) {
// Add all spec files and helpers
if (/spec\/.+.js$/.test(file)) {
tests.push(file);
}
}
}
require.config({
baseUrl: '/base',
paths: {
'backbone': 'libs/backbone',
'marionette': 'libs/backbone.marionette',
'jquery': 'libs/jquery-2.1.1',
'json2': 'libs/json2',
'underscore': 'libs/underscore',
'twig': 'libs/twig',
'editor': 'app/editor',
'widgets': 'app/widgets',
'menu': 'app/menu',
'helpers': 'spec/helpers'
},
map: {
'*': {
'jquery': 'config/jquery/jqueryPrivate'
},
'config/jquery/jqueryPrivate': { 'jquery': 'jquery' }
},
deps: tests,
callback: window.__karma__.start
});
so in my tests,
define([
'app/app',
'backbone',
'editor/editorController',
'editor/editorApp',
], function (
myApp,
Backbone,
editorController
) {
'use strict';
describe('editorApp', function () {
.....
works like a charm, but when I try
define([
'app/common/routerUtilities',
'backbone',
'helpers/testHelpers'
], function (
routerUtilities,
Backbone,
testHelpers
) {
'use strict';
describe('routerUtilities', function () {
...
it fails trying to fetch testHelpers, always get the error even when the module is already loaded. I tried specifying the path in all possible ways besides the shortened one: spec/helpers/testHelpers, /base/spec/helpers/testHelpers, /spec/helpers/testHelpers, ../../helpers/testHelpers, etc...
The file is included in tests array as a dependency (checked), so it's loaded (checked with console.log) along my tests and other test setup modules:
LOG: ['/base/spec/app/appSpec.js',
'/base/spec/app/common/routerUtilitiesSpec.js',
'/base/spec/app/editor/EditorLayoutViewSpec.js',
'/base/spec/app/editor/editorAppSpec.js',
'/base/spec/app/editor/editorControllerSpec.js',
'/base/spec/app/menu/menuControllerSpec.js',
'/base/spec/helpers/envSetup.js',
'/base/spec/helpers/testHelpers.js']
I've checked that is included in window._ karma _.files as well (edited for brevity):
LOG: Object{
/base/bootstrapTests.js: 'c389a1d36d1c48f2879d434b10fd5a25b6b07758',
/base/app/app.js: '7ad39554809146effd20dd1db908fc068f8119ba',
/base/app/common/routerUtilities.js: '4da0e1d1794cccc727b544cacbc6d672c0d9965a',
...
/base/config/marionette/renderer.js: '34a5e729f6133aa13841c5e949307cd437ca331b',
/base/config/marionette/templateCache.js: '9f1901d4c6f43f5f90dadacb1c4ac179efd14b15',
/base/spec/app/appSpec.js: 'e01f4fea3533e25cfcd4f7621e1c1c5559e0eed8',
/base/spec/app/common/routerUtilitiesSpec.js: 'a06b9793a635633d053142dff24d1ba4427dd365',
/base/spec/app/editor/EditorLayoutViewSpec.js: 'a24c7e8742e38b86d626bd6f3e45baacfa6af5eb',
/base/spec/app/editor/editorAppSpec.js: '800c0e8e82840ebd0d1af07c3ec4556a24ee0b04',
/base/spec/app/editor/editorControllerSpec.js: 'd2e259a477da85b6a2f742f5c6c3a4a34b7e340b',
/base/spec/helpers/envSetup.js: '297aa1e59477d967aa210bece1726e8a372cb630',
/base/spec/helpers/testHelpers.js: '5266065d344ca69f8f5980db16bf6d131492ebd0'
}
The content of spec/helpers/testHelpers.js is:
define([
'backbone'
], function (
Backbone
) {
'use strict';
var testHelpers = {
setupRoutingTest: function () {
Backbone.history.start();
Backbone.history.navigate('');
},
teardownRoutingTest: function () {
Backbone.history.navigate('');
Backbone.history.stop();
}
};
return testHelpers;
});
My folder structure is:
|-app
|---common
|---editor
|---menu
|---widgets
|-config
|---jquery
|---marionette
|-entities
|-features
|-gruntTasks
|---lib
|-spec
|---app
|-----common
|-----editor
|-----menu
|-----widgets
|---entities
|---helpers
|-tmp
Hi it looks like the karma-requirejs doesn't like the resources to be loaded into the tests array.
Try to modify the code to exclude the helper files and it could help
var tests = [];
for (var file in window.__karma__.files) {
if (window.__karma__.files.hasOwnProperty(file)) {
// Add all spec files and helpers
if (/spec\/.+.js$/.test(file)) {
tests.push(file);
}
}
}
This drove me a little nuts a while back. Make sure you're using karma-requirejs, not just requirejs.
https://www.npmjs.org/package/karma-requirejs
On that note, don't also load the production version of requirejs.

How to output two files using grunt durandal

I am having a go at grunt for optimizing my Durandal SPA. It seems to work great but now I would like to output a second file called libs.js which is the merged uglified version of all my required libraries but my first dist is getting ignored and still the only file I get is main-built.js
I only get one file so app/libs.js never gets created. I also have no grunt errors.
Here is my Gruntfile:
module.exports = function (grunt) {
grunt.initConfig({
durandal: {
libs: {
src: [
"../scripts/jquery-1.9.1.js",
"../scripts/typeahead.js",
"../scripts/jquery-ui-1.10.3.js",
"../scripts/knockout-3.0.0rc.js",
"../scripts/toastr.js",
"../scripts/q.js",
"../scripts/breeze.min.js",
"../scripts/bootstrap.js",
"../scripts/moment.js",
"../scripts/lodash.js",
"../scripts/respond.js",
"../scripts/knockout-sortable.js",
"../scripts/knockout-bootstrap.js",
"../scripts/knockout.validation.js",
],
dest: 'scripts/libs.js',
options: {
uglify2: {
compress: {
global_defs: {
DEBUG: false
}
}
}
}
},
dist: {
src: [
"app/**/*.*",
"scripts/durandal/**/*.*"
],
options: {
baseUrl: "app/",
mainPath: "app/main.js",
out: "app/main-built.js",
uglify2: {
compress: {
global_defs: {
DEBUG: false
}
}
}
}
}
}
});
grunt.loadTasks('tasks');
grunt.registerTask('default', ['durandal']);
};
This is JavaScript. If you create an object like { a: 'a', a: 'b' }, the first key will be overwritten by the second by the VM.
Instead of configuring it like this:
dist: {
// config goes here
},
dist: {
// config goes here
}
Try
libs: {
// config goes here
},
main: {
// config goes here
}

Categories