Skip to content

Commit 4baf9cd

Browse files
committed
build: introduce webpack instead of broccoli in the build
1 parent 67b577d commit 4baf9cd

File tree

8 files changed

+531
-1
lines changed

8 files changed

+531
-1
lines changed

addon/ng2/commands/build.ts

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
const Command = require('ember-cli/lib/models/command');
2+
const win = require('ember-cli/lib/utilities/windows-admin');
3+
const path = require('path');
4+
5+
const Build = require('../tasks/build');
6+
const BuildWatch = require('../tasks/build-watch');
7+
8+
9+
const webpack = require('webpack');
10+
11+
12+
module.exports = Command.extend({
13+
name: 'build',
14+
description: 'Builds your app and places it into the output path (dist/ by default).',
15+
aliases: ['b'],
16+
17+
availableOptions: [
18+
{ name: 'environment', type: String, default: 'development', aliases: ['e', { 'dev': 'development' }, { 'prod': 'production' }] },
19+
{ name: 'output-path', type: 'Path', default: 'dist/', aliases: ['o'] },
20+
{ name: 'watch', type: Boolean, default: false, aliases: ['w'] },
21+
{ name: 'watcher', type: String },
22+
{ name: 'suppress-sizes', type: Boolean, default: false }
23+
],
24+
25+
run: function(commandOptions) {
26+
// var BuildTask = this.taskFor(commandOptions);
27+
// var buildTask = new BuildTask({
28+
// ui: this.ui,
29+
// analytics: this.analytics,
30+
// project: this.project
31+
// });
32+
// var ShowAssetSizesTask = this.tasks.ShowAssetSizes;
33+
// var showTask = new ShowAssetSizesTask({
34+
// ui: this.ui
35+
// });
36+
//
37+
// return win.checkWindowsElevation(this.ui).then(function () {
38+
// return buildTask.run(commandOptions)
39+
// .then(function () {
40+
// if (!commandOptions.suppressSizes && commandOptions.environment === 'production') {
41+
// return showTask.run({
42+
// outputPath: commandOptions.outputPath
43+
// });
44+
// }
45+
// });
46+
// });
47+
48+
49+
return new Promise((resolve) => {
50+
webpack({
51+
resolve: {
52+
extensions: ['', '.css', '.scss', '.ts', '.js']
53+
},
54+
55+
plugins: [
56+
// new LiveReloadPlugin({
57+
// appendScriptTag: true
58+
// })
59+
],
60+
61+
entry: path.resolve(process.cwd(), './src/main.ts'),
62+
output: {
63+
path: "./dist",
64+
publicPath: 'dist/',
65+
filename: "bundle.js"
66+
},
67+
ts: {
68+
configFileName: './src/tsconfig.json'
69+
},
70+
71+
// devtool: 'source-map',
72+
73+
module: {
74+
loaders: [
75+
{
76+
test: /\.ts$/,
77+
loader: 'ts-loader'
78+
},
79+
{
80+
test: /\.css$/,
81+
loader: 'style-loader'
82+
}
83+
]
84+
},
85+
86+
devServer: {
87+
historyApiFallback: true
88+
}
89+
}, function (err, stats) {
90+
resolve();
91+
console.log(err);
92+
console.log(stats);
93+
console.log('--------');
94+
});
95+
});
96+
},
97+
98+
taskFor: function(options) {
99+
if (options.watch) {
100+
return BuildWatch;
101+
} else {
102+
return Build;
103+
}
104+
}
105+
});
106+
107+
module.exports.overrideCore = true;

addon/ng2/commands/serve.ts

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
const assign = require('lodash/assign');
2+
const Command = require('ember-cli/lib/models/command');
3+
const Promise = require('ember-cli/lib/ext/promise');
4+
const SilentError = require('silent-error');
5+
const PortFinder = require('portfinder');
6+
const win = require('ember-cli/lib/utilities/windows-admin');
7+
const EOL = require('os').EOL;
8+
9+
PortFinder.basePort = 49152;
10+
11+
const getPort = Promise.denodeify(PortFinder.getPort);
12+
const defaultPort = process.env.PORT || 4200;
13+
14+
15+
module.exports = Command.extend({
16+
name: 'serve',
17+
description: 'Builds and serves your app, rebuilding on file changes.',
18+
aliases: ['server', 's'],
19+
20+
availableOptions: [
21+
{ name: 'port', type: Number, default: defaultPort, aliases: ['p'] },
22+
{ name: 'host', type: String, aliases: ['H'], description: 'Listens on all interfaces by default' },
23+
{ name: 'proxy', type: String, aliases: ['pr', 'pxy'] },
24+
{ name: 'insecure-proxy', type: Boolean, default: false, aliases: ['inspr'], description: 'Set false to proxy self-signed SSL certificates' },
25+
{ name: 'watcher', type: String, default: 'events', aliases: ['w'] },
26+
{ name: 'live-reload', type: Boolean, default: true, aliases: ['lr'] },
27+
{ name: 'live-reload-host', type: String, aliases: ['lrh'], description: 'Defaults to host' },
28+
{ name: 'live-reload-base-url', type: String, aliases: ['lrbu'], description: 'Defaults to baseURL' },
29+
{ name: 'live-reload-port', type: Number, aliases: ['lrp'], description: '(Defaults to port number within [49152...65535])' },
30+
{ name: 'live-reload-live-css', type: Boolean, default: true, description: 'Whether to live reload CSS (default true)' },
31+
{ name: 'environment', type: String, default: 'development', aliases: ['e', { 'dev': 'development' }, { 'prod': 'production' }] },
32+
{ name: 'output-path', type: 'Path', default: 'dist/', aliases: ['op', 'out'] },
33+
{ name: 'ssl', type: Boolean, default: false },
34+
{ name: 'ssl-key', type: String, default: 'ssl/server.key' },
35+
{ name: 'ssl-cert', type: String, default: 'ssl/server.crt' }
36+
],
37+
38+
run: function(commandOptions) {
39+
commandOptions.liveReloadHost = commandOptions.liveReloadHost || commandOptions.host;
40+
41+
return this._checkExpressPort(commandOptions)
42+
.then(this._autoFindLiveReloadPort.bind(this))
43+
.then(function(commandOptions) {
44+
commandOptions = assign({}, commandOptions, {
45+
baseURL: this.project.config(commandOptions.environment).baseURL || '/'
46+
});
47+
48+
if (commandOptions.proxy) {
49+
if (!commandOptions.proxy.match(/^(http:|https:)/)) {
50+
var message = 'You need to include a protocol with the proxy URL.' + EOL + 'Try --proxy http://' + commandOptions.proxy;
51+
52+
return Promise.reject(new SilentError(message));
53+
}
54+
}
55+
56+
var ServeTask = require('../tasks/serve');
57+
var serve = new ServeTask({
58+
ui: this.ui,
59+
analytics: this.analytics,
60+
project: this.project
61+
});
62+
63+
return win.checkWindowsElevation(this.ui).then(function() {
64+
return serve.run(commandOptions);
65+
});
66+
}.bind(this));
67+
},
68+
69+
_checkExpressPort: function(commandOptions) {
70+
return getPort({ port: commandOptions.port, host: commandOptions.host })
71+
.then(function(foundPort) {
72+
73+
if (commandOptions.port !== foundPort && commandOptions.port !== 0) {
74+
var message = 'Port ' + commandOptions.port + ' is already in use.';
75+
return Promise.reject(new SilentError(message));
76+
}
77+
78+
// otherwise, our found port is good
79+
commandOptions.port = foundPort;
80+
return commandOptions;
81+
82+
}.bind(this));
83+
},
84+
85+
_autoFindLiveReloadPort: function(commandOptions) {
86+
return getPort({ port: commandOptions.liveReloadPort, host: commandOptions.liveReloadHost })
87+
.then(function(foundPort) {
88+
89+
// if live reload port matches express port, try one higher
90+
if (foundPort === commandOptions.port) {
91+
commandOptions.liveReloadPort = foundPort + 1;
92+
return this._autoFindLiveReloadPort(commandOptions);
93+
}
94+
95+
// port was already open
96+
if (foundPort === commandOptions.liveReloadPort) {
97+
return commandOptions;
98+
}
99+
100+
// use found port as live reload port
101+
commandOptions.liveReloadPort = foundPort;
102+
return commandOptions;
103+
104+
}.bind(this));
105+
}
106+
});
107+
108+
module.exports.overrideCore = true;

addon/ng2/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ module.exports = {
1212

1313
includedCommands: function () {
1414
return {
15+
'build': require('./commands/build'),
16+
'serve': require('./commands/serve'),
1517
'new': require('./commands/new'),
1618
'generate': require('./commands/generate'),
1719
'init': require('./commands/init'),

addon/ng2/models/builder.ts

+161
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
const fs = require('fs-extra');
2+
const existsSync = require('exists-sync');
3+
const path = require('path');
4+
const Promise = require('ember-cli/lib/ext/promise');
5+
const Task = require('ember-cli/lib/models/task');
6+
const SilentError = require('silent-error');
7+
const chalk = require('chalk');
8+
const attemptNeverIndex = require('ember-cli/lib/utilities/attempt-never-index');
9+
const findBuildFile = require('ember-cli/lib/utilities/find-build-file');
10+
const viz = require('broccoli-viz');
11+
const FSMonitor = require('fs-monitor-stack');
12+
const Sync = require('tree-sync');
13+
const mkdirp = require('mkdirp');
14+
15+
let resolve = null;
16+
let promise = new Promise((r) => resolve = r);
17+
18+
19+
20+
21+
var signalsTrapped = false;
22+
var buildCount = 0;
23+
24+
function outputViz(count, result, monitor) {
25+
var processed = viz.process(result.graph);
26+
27+
processed.forEach(function(node) {
28+
node.stats.fs = monitor.statsFor(node);
29+
});
30+
31+
fs.writeFileSync('graph.' + count + '.dot', viz.dot(processed));
32+
fs.writeFileSync('graph.' + count + '.json', JSON.stringify({
33+
summary: {
34+
buildCount: count,
35+
output: result.directory,
36+
totalTime: result.totalTime,
37+
totalNodes: processed.length,
38+
stats: {
39+
fs: monitor.totalStats()
40+
}
41+
},
42+
nodes: processed
43+
}));
44+
}
45+
46+
module.exports = Task.extend({
47+
setupBuilder: function() {
48+
this.environment = this.environment || 'development';
49+
process.env.ANGULAR_ENV = process.env.ANGULAR_ENV || process.env.EMBER_CLI || this.environment;
50+
process.env.EMBER_ENV = process.env.ANGULAR_ENV;
51+
52+
var buildFile = findBuildFile('angular-cli-build.js');
53+
this.tree = buildFile({ project: this.project });
54+
55+
if (webpack) {
56+
console.log('webpack');
57+
} else {
58+
var broccoli = require('ember-cli-broccoli');
59+
this.builder = new broccoli.Builder(this.tree);
60+
}
61+
},
62+
63+
trapSignals: function() {
64+
if (!signalsTrapped) {
65+
process.on('SIGINT', this.onSIGINT.bind(this));
66+
process.on('SIGTERM', this.onSIGTERM.bind(this));
67+
process.on('message', this.onMessage.bind(this));
68+
signalsTrapped = true;
69+
}
70+
},
71+
72+
init: function() {
73+
this.setupBuilder();
74+
this.trapSignals();
75+
},
76+
77+
/**
78+
Determine whether the output path is safe to delete. If the outputPath
79+
appears anywhere in the parents of the project root, the build would
80+
delete the project directory. In this case return `false`, otherwise
81+
return `true`.
82+
*/
83+
canDeleteOutputPath: function(outputPath) {
84+
var rootPathParents = [this.project.root];
85+
var dir = path.dirname(this.project.root);
86+
rootPathParents.push(dir);
87+
while (dir !== path.dirname(dir)) {
88+
dir = path.dirname(dir);
89+
rootPathParents.push(dir);
90+
}
91+
return rootPathParents.indexOf(outputPath) === -1;
92+
},
93+
94+
copyToOutputPath: function(inputPath) {
95+
var outputPath = this.outputPath;
96+
97+
mkdirp.sync(outputPath);
98+
99+
if (!this.canDeleteOutputPath(outputPath)) {
100+
throw new SilentError('Using a build destination path of `' + outputPath + '` is not supported.');
101+
}
102+
103+
var sync = this._sync;
104+
if (sync === undefined) {
105+
this._sync = sync = new Sync(inputPath, path.resolve(this.outputPath));
106+
}
107+
108+
sync.sync();
109+
},
110+
111+
build: function(...args: any[]) {
112+
attemptNeverIndex('tmp');
113+
return promise;
114+
// return Promise.resolve();
115+
// if (this.webpack) {
116+
// console.log(1, process.cwd());
117+
// return new Promise((resolve, reject) => {
118+
// this.webpack.run((err, stats) => {
119+
// console.log(!!err, stats);
120+
// if (err) {
121+
// reject(err);
122+
// }
123+
// resolve();
124+
// });
125+
// });
126+
// }
127+
// return this.builder.build(...args);
128+
},
129+
130+
cleanup: function() {
131+
var ui = this.ui;
132+
133+
// if (this.webpack) {
134+
// this.webpack.cleanupAndExit();
135+
return Promise.resolve();
136+
// } else {
137+
// return this.builder.cleanup().catch(function (err) {
138+
// ui.writeLine(chalk.red('Cleanup error.'));
139+
// ui.writeError(err);
140+
// });
141+
// }
142+
},
143+
144+
cleanupAndExit: function() {
145+
this.cleanup().finally(function() {
146+
process.exit(1);
147+
});
148+
},
149+
150+
onSIGINT: function() {
151+
this.cleanupAndExit();
152+
},
153+
onSIGTERM: function() {
154+
this.cleanupAndExit();
155+
},
156+
onMessage: function(message) {
157+
if (message.kill) {
158+
this.cleanupAndExit();
159+
}
160+
}
161+
});

0 commit comments

Comments
 (0)