Skip to content

Commit 04a6823

Browse files
authored
Merge pull request #2 from ololabs/webpack
olo-gulp-helpers: add Webpack/TypeScript support
2 parents 5782948 + 6d8c608 commit 04a6823

File tree

4 files changed

+247
-34
lines changed

4 files changed

+247
-34
lines changed

packages/olo-gulp-helpers/.npmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
save-exact = true
+141-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
22

3+
var fs = require('fs');
34
var path = require('path');
45
var process = require('process');
56
var gulp = require('gulp');
@@ -11,30 +12,162 @@ var rev = require('gulp-rev');
1112
var babel = require('gulp-babel');
1213
var gulpif = require('gulp-if');
1314
var plumber = require('gulp-plumber');
14-
var teamcity = require('eslint-teamcity');
15+
var teamcityESLintFormatter = require('eslint-teamcity');
16+
var gulpWebpack = require('gulp-webpack');
17+
var webpack = require('webpack');
18+
var typings = require('gulp-typings');
19+
var tslint = require('gulp-tslint');
20+
var _ = require('lodash');
21+
var WebpackMd5Hash = require('webpack-md5-hash');
22+
var Server = require('karma').Server;
1523

16-
function lint(scripts) {
24+
function lintJavaScript(scripts) {
1725
return gulp.src(scripts)
1826
.pipe(eslint())
19-
.pipe(eslint.format(process.env.TEAMCITY_VERSION ? teamcity : undefined))
27+
.pipe(eslint.format(process.env.TEAMCITY_VERSION ? teamcityESLintFormatter : undefined))
2028
.pipe(eslint.failAfterError());
2129
}
2230

23-
function createBundle(bundleName, bundleFiles, outputPath, currentDirectory, catchErrors) {
31+
function lintTypeScript(scripts) {
32+
return gulp.src(scripts)
33+
.pipe(tslint({
34+
formatter: process.env.TEAMCITY_VERSION ? 'tslint-teamcity-reporter' : undefined
35+
}))
36+
.pipe(tslint.report());
37+
}
38+
39+
function createBundle(bundleName, bundleFiles, outputPath, currentDirectory, watchMode) {
2440
console.log('Creating script bundle: ' + bundleName);
2541

2642
return gulp.src(bundleFiles)
27-
.pipe(gulpif(catchErrors, plumber()))
43+
.pipe(gulpif(watchMode, plumber()))
2844
.pipe(sourcemaps.init())
2945
.pipe(babel())
3046
.pipe(uglify())
3147
.pipe(concat({ path: bundleName, cwd: currentDirectory }))
3248
.pipe(rev())
3349
.pipe(sourcemaps.write('.'))
34-
.pipe(gulp.dest(path.join(outputPath)));
50+
.pipe(gulp.dest(outputPath));
51+
}
52+
53+
function createWebpackBundle(bundleName, entryScriptPath, outputPath, watchMode) {
54+
console.log('Creating webpack script bundle: ' + bundleName);
55+
56+
var baseName = bundleName.replace(/(.*)\..*$/, '$1');
57+
58+
return gulp.src(entryScriptPath)
59+
.pipe(gulpif(watchMode, plumber()))
60+
.pipe(gulpWebpack({
61+
devtool: 'source-map',
62+
entry: { bundle: entryScriptPath },
63+
exclude: {},
64+
output: { filename: baseName + '-[chunkhash].js' },
65+
watch: watchMode,
66+
module: {
67+
loaders: [{
68+
test: /\.ts(x?)$/,
69+
loaders: ['ts'],
70+
exclude: /(node_modules)/
71+
}]
72+
},
73+
plugins: _.without([
74+
new WebpackMd5Hash(),
75+
new webpack.NoErrorsPlugin(),
76+
new webpack.DefinePlugin({
77+
'process.env': {
78+
'NODE_ENV': JSON.stringify(process.env.TEAMCITY_VERSION ? 'production' : 'development')
79+
}
80+
}),
81+
process.env.TEAMCITY_VERSION && new webpack.optimize.UglifyJsPlugin({
82+
compress: { warnings: false }
83+
}),
84+
function() {
85+
this.plugin('done', function(stats) {
86+
if (!watchMode && stats.compilation.errors && stats.compilation.errors.length) {
87+
console.error('Failed to generate webpack: ' + bundleName);
88+
89+
stats.compilation.errors.forEach(function(error) {
90+
console.error('in ' + error.file + ':');
91+
console.error(error.message);
92+
});
93+
94+
throw new Error('Error generating webpack');
95+
}
96+
97+
// TODO: introduce a file lock here to avoid any concurrency issues (for now we just process these serially)
98+
var manifestPath = path.join(process.cwd(), 'rev-manifest.json');
99+
100+
var hashedFileName = Object.keys(stats.compilation.assets)
101+
.filter(function(key) { return key.endsWith('.js'); })[0];
102+
103+
var manifestContents = fs.existsSync(manifestPath) ? JSON.parse(fs.readFileSync(manifestPath, 'utf8')) : {};
104+
manifestContents[bundleName] = hashedFileName;
105+
106+
fs.writeFileSync(manifestPath, JSON.stringify(manifestContents, null, ' '));
107+
});
108+
}
109+
], undefined),
110+
resolve: {
111+
extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js', '.jsx']
112+
}
113+
}))
114+
.pipe(gulp.dest(outputPath));
115+
}
116+
117+
function restoreTypings(typingsPaths) {
118+
return gulp.src(typingsPaths)
119+
.pipe(typings());
120+
}
121+
122+
function runKarmaTests(config, callback) {
123+
new Server({
124+
basePath: '',
125+
frameworks: config.frameworks,
126+
files: config.files,
127+
exclude: [],
128+
preprocessors: {
129+
'**/*.ts': ['webpack'],
130+
'**/*.tsx': ['webpack']
131+
},
132+
webpack: {
133+
module: {
134+
loaders: _.concat(
135+
[{
136+
test: /\.ts(x?)$/,
137+
loaders: ['ts'],
138+
exclude: /(node_modules)/
139+
}],
140+
config.webpack.loaders || []),
141+
noParse: [
142+
/\/sinon\.js/,
143+
]
144+
},
145+
resolve: {
146+
extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js', '.jsx'],
147+
alias: {
148+
sinon: 'sinon/pkg/sinon.js',
149+
}
150+
},
151+
externals: config.webpack.externals
152+
},
153+
reporters: [process.env.TEAMCITY_VERSION ? 'teamcity' : 'mocha'],
154+
mochaReporter: {
155+
output: 'autowatch'
156+
},
157+
port: 9876,
158+
colors: true,
159+
autoWatch: true,
160+
browsers: ['PhantomJS'],
161+
concurrency: Infinity,
162+
singleRun: !config.watch
163+
}, callback).start();
35164
}
36165

37166
module.exports = {
38-
lint: lint,
39-
createBundle: createBundle
167+
lintJavaScript: lintJavaScript,
168+
lintTypeScript: lintTypeScript,
169+
createBundle: createBundle,
170+
createWebpackBundle: createWebpackBundle,
171+
restoreTypings: restoreTypings,
172+
runKarmaTests: runKarmaTests
40173
};

packages/olo-gulp-helpers/index.js

+64-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ var process = require('process');
55
var merge = require('merge-stream');
66
var gulp = require('gulp');
77
var rev = require('gulp-rev');
8+
var _ = require('lodash');
89
var scriptHelpers = require('./helpers/scripts');
910
var styleHelpers = require('./helpers/styles');
1011

@@ -14,6 +15,14 @@ var bundleDefaults = {
1415
outputPath: './Content/bundles/',
1516
bundlesForFile: null
1617
};
18+
var karmaDefaults = {
19+
frameworks: ['mocha', 'chai', 'sinon-chai'],
20+
watch: false,
21+
webpack: {
22+
loaders: [],
23+
externals: {}
24+
}
25+
};
1726

1827
function getBundles(assetConfigFullPath, bundlesForFile) {
1928
var allBundles = require(assetConfigFullPath).bundles;
@@ -37,25 +46,43 @@ function getBundles(assetConfigFullPath, bundlesForFile) {
3746
}, {});
3847
}
3948

40-
function bundle(options, catchErrors) {
49+
function getWebpackBundles(assetConfigFullPath) {
50+
var allBundles = require(assetConfigFullPath).webpack || {};
51+
52+
return Object.keys(allBundles).reduce(function (bundles, name) {
53+
bundles[name] = allBundles[name].startsWith('./')
54+
? allBundles[name]
55+
: ('./' + allBundles[name]);
56+
57+
return bundles;
58+
}, {});
59+
}
60+
61+
function bundle(options, watchMode) {
4162
var config = Object.assign({}, bundleDefaults, options);
4263
var assetConfigFullPath = path.join(currentDirectory, config.assetConfigPath);
4364

4465
var bundles = getBundles(assetConfigFullPath, config.bundlesForFile);
4566
var bundleTasks = Object.keys(bundles).map(function (bundleName) {
4667
if (bundleName.toLowerCase().endsWith('.css')) {
47-
return styleHelpers.createBundle(bundleName, bundles[bundleName], config.outputPath, currentDirectory, catchErrors);
68+
return styleHelpers.createBundle(bundleName, bundles[bundleName], config.outputPath, currentDirectory, watchMode);
4869
}
4970

50-
return scriptHelpers.createBundle(bundleName, bundles[bundleName], config.outputPath, currentDirectory, catchErrors);
71+
return scriptHelpers.createBundle(bundleName, bundles[bundleName], config.outputPath, currentDirectory, watchMode);
5172
});
52-
53-
return merge.apply(this, bundleTasks)
73+
var allBundleTasks = merge.apply(this, bundleTasks)
5474
.pipe(rev.manifest({
5575
merge: true,
5676
cwd: ''
5777
}))
5878
.pipe(gulp.dest('./'));
79+
80+
var webpackBundles = getWebpackBundles(assetConfigFullPath);
81+
var webpackBundleTasks = config.bundlesForFile ? [] : Object.keys(webpackBundles).map(function (bundleName) {
82+
return scriptHelpers.createWebpackBundle(bundleName, webpackBundles[bundleName], config.outputPath, watchMode);
83+
});
84+
85+
return merge.call(this, _.flatten([allBundleTasks, webpackBundleTasks]));
5986
}
6087

6188
function watch(incrementalFilesToWatch, bundleOptions) {
@@ -70,6 +97,13 @@ function watch(incrementalFilesToWatch, bundleOptions) {
7097
gulp.watch(config.assetConfigPath, function() {
7198
bundle(config, true);
7299
});
100+
101+
var assetConfigFullPath = path.join(currentDirectory, config.assetConfigPath);
102+
var webpackBundles = getWebpackBundles(assetConfigFullPath);
103+
104+
Object.keys(webpackBundles).forEach(function (bundleName) {
105+
scriptHelpers.createWebpackBundle(bundleName, webpackBundles[bundleName], config.outputPath, true);
106+
});
73107
}
74108

75109
function arrayify(input) {
@@ -81,16 +115,35 @@ function arrayify(input) {
81115
}
82116

83117
function lint(options) {
84-
var config = Object.assign({}, bundleDefaults, options);
85-
var scripts = arrayify(config.scripts).map(function(localScriptPath) {
86-
return path.join(currentDirectory, localScriptPath);
87-
});
118+
function getScripts(scripts) {
119+
return _.concat(
120+
arrayify(scripts || []).map(function(localScriptPath) {
121+
return path.join(currentDirectory, localScriptPath);
122+
}),
123+
['!**/typings/**/*', '!**/node_modules/**/*']);
124+
}
88125

89-
scriptHelpers.lint(scripts);
126+
var config = Object.assign({}, bundleDefaults, options);
127+
var javascripts = getScripts(config.scripts);
128+
var typescripts = getScripts(config.typescripts);
129+
130+
return merge(
131+
scriptHelpers.lintJavaScript(javascripts),
132+
scriptHelpers.lintTypeScript(typescripts)
133+
);
134+
}
135+
136+
function test(options, callback) {
137+
var config = _.merge({}, karmaDefaults, options);
138+
config.frameworks = _.concat(karmaDefaults.frameworks, options.frameworks || []);
139+
140+
return scriptHelpers.runKarmaTests(config, callback);
90141
}
91142

92143
module.exports = {
93144
lint: lint,
94145
bundle: bundle,
95-
watch: watch
146+
watch: watch,
147+
test: test,
148+
restoreTypings: scriptHelpers.restoreTypings
96149
};
+41-15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "olo-gulp-helpers",
3-
"version": "0.1.1",
3+
"version": "0.2.1",
44
"description": "Helpers for Olo's gulp build pipeline",
55
"main": "index.js",
66
"scripts": {
@@ -11,19 +11,45 @@
1111
"url": "https://github.com/ololabs/javascript"
1212
},
1313
"dependencies": {
14-
"babel-preset-es2015": "^6.5.0",
15-
"eslint-teamcity": "^1.0.0",
16-
"gulp": "^3.9.1",
17-
"gulp-babel": "^6.1.2",
18-
"gulp-concat": "^2.6.0",
19-
"gulp-eslint": "^2.0.0",
20-
"gulp-if": "^2.0.0",
21-
"gulp-plumber": "^1.1.0",
22-
"gulp-rev": "^7.0.0",
23-
"gulp-sass": "^2.2.0",
24-
"gulp-sourcemaps": "^1.6.0",
25-
"gulp-uglify": "^1.5.2",
26-
"merge-stream": "^1.0.0"
14+
"babel-preset-es2015": "6.13.2",
15+
"beautylog": "5.0.14",
16+
"chai": "3.5.0",
17+
"eslint-teamcity": "1.1.0",
18+
"gulp": "3.9.1",
19+
"gulp-babel": "6.1.2",
20+
"gulp-concat": "2.6.0",
21+
"gulp-eslint": "3.0.1",
22+
"gulp-if": "2.0.1",
23+
"gulp-plumber": "1.1.0",
24+
"gulp-rev": "7.0.0",
25+
"gulp-sass": "2.2.0",
26+
"gulp-sourcemaps": "1.6.0",
27+
"gulp-tslint": "6.0.2",
28+
"gulp-typescript": "2.13.6",
29+
"gulp-typings": "2.0.3",
30+
"gulp-uglify": "1.5.2",
31+
"gulp-webpack": "1.5.0",
32+
"karma": "1.1.2",
33+
"karma-chai": "0.1.0",
34+
"karma-mocha": "1.1.1",
35+
"karma-mocha-reporter": "2.1.0",
36+
"karma-phantomjs-launcher": "1.0.1",
37+
"karma-sinon-chai": "1.2.3",
38+
"karma-teamcity-reporter": "1.0.0",
39+
"karma-typescript-preprocessor2": "1.2.1",
40+
"karma-webpack": "1.7.0",
41+
"lodash": "4.14.1",
42+
"merge-stream": "1.0.0",
43+
"mocha": "3.0.1",
44+
"sinon": "1.17.5",
45+
"sinon-chai": "2.8.0",
46+
"source-map-loader": "0.1.5",
47+
"ts-loader": "0.8.2",
48+
"tslint": "3.14.0",
49+
"tslint-teamcity-reporter": "1.0.0",
50+
"typescript": "1.8.10",
51+
"webpack": "1.13.1",
52+
"webpack-md5-hash": "0.0.5"
2753
},
2854
"keywords": [
2955
"olo",
@@ -37,6 +63,6 @@
3763
"homepage": "https://github.com/ololabs/javascript",
3864
"devDependencies": {
3965
"eslint": "^2.5.1",
40-
"eslint-config-olo": "^0.1.0"
66+
"eslint-config-olo": "^0.1.1"
4167
}
4268
}

0 commit comments

Comments
 (0)