Skip to content

Commit

Permalink
Set up modular build to support custom CSS.
Browse files Browse the repository at this point in the history
This makes some changes to our modular build to not pre-bundle public modules. It also enables support for compiling custom CSS by providing a Node build script to invoke the r.js optimizer instead of relying on the commandline tool.
  • Loading branch information
xirzec committed Dec 17, 2014
1 parent 97ee8c3 commit 7fda0f9
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 167 deletions.
2 changes: 1 addition & 1 deletion gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
grunt.registerTask("_copyToTsBuild", ["copy:srcjs"])

// Other tasks
grunt.registerTask("modules", ["clean:modules", "requirejs:publicModules", "replace:base"]);
grunt.registerTask("modules", ["clean:modules", "build-modules", "replace:base"]);
grunt.registerTask("lint", ["jshint", "jscs"]);
grunt.registerTask("saucelabs", ["connect:saucelabs", "saucelabs-qunit", "post-tests-results"]);
};
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
"http-post": "~0.1.1",
"less": "^1.7.4",
"load-grunt-tasks": "^0.6.0",
"madge": "^0.3.1",
"minimist": "0.2.0",
"qunitjs": "~1.14.0",
"text-table": "~0.2.0",
Expand Down
53 changes: 53 additions & 0 deletions tasks/build-modules.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
(function () {
"use strict";

var path = require('path');
var fs = require("fs-extra");
var config = require("../config.js");

module.exports = function (grunt) {

grunt.registerTask("build-modules", ["ts:src", "_copyToTsBuild", "copy:modules", "_setupModules"]);
grunt.registerTask("_setupModules", "Set up the modules package", function () {

// rename the main file
fs.renameSync(path.join(config.modulesOutput, "WinJS.js"), path.join(config.modulesOutput, "WinJS-custom.js"));

// require.js copies some undesirable source files over
var toRemove = [
"_build.js",
"WinJS/Utilities/_TelemetryImpl.js"
];
toRemove.forEach(function (item) {
fs.removeSync(path.join(config.modulesOutput, item));
});

var requirejs = grunt.config.get("requirejs");

var pkgRoot = "node_modules/winjs-modules/";
var requireConfig = {
baseUrl: ".",
name: "WinJS-custom",
deps: ["amd"],
optimize: "none",
useStrict: true,
out: "bin/js/WinJS.js",
wrap: {
start: requirejs.header("WinJS-custom", []),
end: requirejs.footer("WinJS-custom"),
},
paths: {
"amd": pkgRoot + "amd",
"require-style": pkgRoot + "require-style",
"require-json": pkgRoot + "require-json",
"WinJS": pkgRoot + "WinJS"
},
findNestedDependencies: true
};
var output = JSON.stringify(requireConfig, null, 4);
fs.writeFileSync(path.join(config.modulesOutput, "example.config.js"), output);
});

};
})();
24 changes: 24 additions & 0 deletions tasks/options/copy.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,30 @@
src: ["**/*.js", "**/*.resjson"],
dest: config.compiledTsOutput
}]
},

modules: {
files: [{
expand: true,
cwd: config.compiledTsOutput,
src: ["**/*.js", "**/*.resjson"],
dest: config.modulesOutput
}, {
expand: true,
cwd: "src/fonts",
src: ["**.ttf"],
dest: config.modulesOutput + "fonts/"
}, {
expand: true,
cwd: "src/less",
src: ["**.less"],
dest: config.modulesOutput + "less/"
}, {
expand: true,
cwd: "tasks/utilities",
src: ["require-*.js", "build-winjs.js"],
dest: config.modulesOutput
}]
}
};
})();
170 changes: 5 additions & 165 deletions tasks/options/requirejs.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,129 +3,9 @@
"use strict";

var path = require('path');
var madge = require('madge');
var config = require("../../config.js");
var grunt = config.grunt;

var bundles = {};

function generatePublicModules() {
var moduleConfig = [];
var dependencies = madge(config.compiledTsOutput, { format: 'amd' }).tree;

Object.keys(dependencies).forEach(function (module) {
// filter for only public modules
if (startsWith(module, "WinJS/") && module.indexOf('_') === -1) {

var privateModules = [];
var processed = dependencies[module].slice(0);

if (module === 'WinJS/Core') {
privateModules.push('require-json!en-US/ui.resjson');
}

var excludes = dependencies[module].slice(0).filter(function (dep) {
if (startsWith(dep, module)) {
privateModules.push(dep);
return false;
}
return true;
});

var processQueue = processed.slice(0);

while (processQueue.length) {
var next = processQueue.pop();
dependencies[next].forEach(function (dep) {
if (processed.indexOf(dep) === -1) {
processQueue.push(dep);
}
if (startsWith(dep, module)) {
if (privateModules.indexOf(dep) === -1) {
privateModules.push(dep);
}
} else if (excludes.indexOf(dep) === -1) {
excludes.push(dep);
}
});
}

if (privateModules.length) {
bundles[module] = privateModules;
}

var remove = ['require-style', 'require-json'];

if (module !== 'WinJS/Core') {
remove.push('require-json!en-US/ui.resjson');
}

moduleConfig.push({
name: module,
exclude: remove,
excludeShallow: excludes,
include: []
});

}
});

return moduleConfig;
}

function moduleDone(done, output) {
var fs = require("fs-extra");

// require-style seems to build in WinJS rather than in the root
fs.copySync(path.join(config.modulesOutput, "WinJS/css"), path.join(config.modulesOutput, "css"));
// rename the main file
fs.copySync(path.join(config.modulesOutput, "WinJS.js"), path.join(config.modulesOutput, "WinJS-custom.js"));
// replace require-style and require-json with a stub
fs.writeFileSync(path.join(config.modulesOutput, "require-style.js"), config.copyright + "define({ load: function (name, req, onload, config) { onload(); }});");
fs.writeFileSync(path.join(config.modulesOutput, "require-json.js"), config.copyright + "define({ load: function (name, req, onload, config) { onload(); }});");

// require.js copies some undesirable source files over
var toRemove = [
"en-US",
"less",
"WinJS.js",
"WinJS/css",
"WinJS/Core",
"WinJS/Controls/AppBar",
"WinJS/Utilities/_TelemetryImpl.js"
];
toRemove.forEach(function (item) {
fs.removeSync(path.join(config.modulesOutput, item));
});


var pkgRoot = "node_modules/winjs-modules/";
var requireConfig = {
baseUrl: ".",
name: "WinJS-custom",
deps: ["amd"],
optimize: "none",
useStrict: true,
out: "bin/WinJS.js",
wrap: {
start: header("WinJS-custom", []),
end: footer("WinJS-custom"),
},
paths: {
"amd": pkgRoot + "amd",
"require-style": pkgRoot + "require-style",
"require-json": pkgRoot + "require-json",
"WinJS": pkgRoot + "WinJS"
},
bundles: bundles,
findNestedDependencies: true
};
var output = "(" + JSON.stringify(requireConfig, null, 4) + ")";
fs.writeFileSync(path.join(config.modulesOutput, "example.build.js"), output);

done();
}

var rootPath = path.resolve();
var realFileNames = [];

Expand All @@ -145,10 +25,6 @@
}
}

function startsWith(str, target) {
return str.indexOf(target) === 0;
}

// ensure that the files discovered by requireJS have appropriate
// casing so that non-Windows builds will work.
function done(done, output) {
Expand Down Expand Up @@ -218,27 +94,6 @@
"\n";
}

module.exports = {

//
// Configs which are themselves a independent file can use default options and the
// onefile grunt task and thus are not listed here
//

// Modules built for people who want to use custom builds
publicModules: {
options: {
skipDirOptimize: true,
removeCombined: true,
fileExclusionRegExp: /^(library|\w+\.(md|htm|txt))$/i,
dir: config.modulesOutput,
modules: publicModules,
done: moduleDone
}
}

};

function defaults(key, buildConfig) {
buildConfig = buildConfig || {};
var options = buildConfig.options = buildConfig.options || {};
Expand Down Expand Up @@ -282,24 +137,9 @@
return buildConfig;
}

// Shared options
Object.keys(module.exports).forEach(function (key) {
var buildConfig = module.exports[key];
defaults(key, buildConfig);
});

module.exports.defaults = defaults;

var publicModules = null;

Object.defineProperty(module.exports.publicModules.options, "modules", {
get: function () {
if (!publicModules) {
publicModules = generatePublicModules();
}
return publicModules;
},
enumerable: true,
configurable: true
});
module.exports = {
defaults: defaults,
header: header,
footer: footer
};
})();
14 changes: 14 additions & 0 deletions tasks/utilities/build-winjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
"use strict";
var requirejs = require('requirejs');
var fs = require('fs');

var options = JSON.parse(fs.readFileSync('config.js', 'utf8'));

requirejs.optimize(options, function (buildOutput) {
console.log("Success");
console.log(buildOutput);
}, function (err) {
console.log("Error");
console.log(err);
});

0 comments on commit 7fda0f9

Please sign in to comment.