From 91610ca62d782fc46e08b447f358a69c474cd33f Mon Sep 17 00:00:00 2001 From: PawelGutkowski Date: Wed, 27 Apr 2016 15:26:42 +0200 Subject: [PATCH 1/2] RA-1121 migrate to webpack --- .gitignore | 3 + README.md | 40 +++-- app/index.js | 57 ++----- app/templates/README.md | 53 +++--- app/templates/_package.json | 38 ++++- app/templates/bowerrc | 3 - app/templates/gulpfile.js | 135 --------------- app/templates/{ => img}/omrs-button.png | Bin .../{ => img}/openmrs-with-title-small.png | Bin app/templates/index.html | 9 +- app/templates/webpack.config.js | 158 ++++++++++++++++++ package.json | 2 +- test/dependencies.js | 4 +- test/general.js | 18 +- 14 files changed, 271 insertions(+), 249 deletions(-) delete mode 100644 app/templates/bowerrc delete mode 100644 app/templates/gulpfile.js rename app/templates/{ => img}/omrs-button.png (100%) rename app/templates/{ => img}/openmrs-with-title-small.png (100%) create mode 100644 app/templates/webpack.config.js diff --git a/.gitignore b/.gitignore index 3c3629e..67943f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ node_modules +.project +*~ +npm-debug.log diff --git a/README.md b/README.md index 92d7863..a98170d 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ The following features are currently supported: - [x] Scaffold basic OWA folder structure and files - - [x] Production build with [Gulp](http://gulpjs.com/) - - [x] Local deploy with Gulp - - [x] Package management with [Bower](http://bower.io/) + - [x] Production build with [Webpack](https://webpack.github.io/) + - [x] Local deploy with Webpack + - [x] Package management with [npm](http://npmjs.com/) - [x] Live reload, interaction sync and more with [Browsersync](https://www.browsersync.io/) ## Getting Started @@ -25,32 +25,44 @@ The following features are currently supported: - Install the generator: `npm install --global generator-openmrs-owa` - Create directory for your app: `mkdir openmrs-owa-myapp && cd $_` - Run `yo openmrs-owa` to scaffold the Open Web App - - Run `gulp` to build distributable zip file - - Run `gulp deploy-local` to deploy directly to your local server - - Run `gulp watch` for live reloading and more + - Run `npm run build:prod` to build distributable zip file + - Run `npm run build:deploy` to deploy directly to your local server + - Run `npm run watch` for live reloading and more ## Extending -Install Bower packages dependencies as follows: +Install [npm](http://npmjs.com/) packages dependencies as follows: -```` -bower install --save +````sh +npm install --save ```` -Be sure to include the following in your `html` files at the position you want the Bower dependencies injected: +To use the installed package, import it as follows: +````js +//import and assign to variable +import variableName from 'package'; ```` - - + +To contain package in vendor bundle, remember to add it to vendor entry point array, eg.: + +````js +entry: { + app : `${__dirname}/app/js/owa.js`, + css: `${__dirname}/app/css/owa.css`, + vendor : [ + 'package', + ...//other packages in vendor bundle + ] +}, ```` -Do the same for your Bower stylesheet dependencies, but replace `js` with `css`. Any files that you add manually must be added in the `app` directory. ## Options - `--skip-welcome-message` Skips Yeoman's greeting before displaying options. - - `--skip-install` Skips automatically running `bower` and `npm`. + - `--skip-install` Skips automatically running `npm install`. ## Environment Variables diff --git a/app/index.js b/app/index.js index fe5ecde..545c601 100644 --- a/app/index.js +++ b/app/index.js @@ -64,7 +64,7 @@ module.exports = generators.Base.extend({ name: 'appName', message: 'What is your app name?', validate: function(input) { - if (input == null || input == "") { + if (input === null || input === "") { return "App name is required"; } else { return true; @@ -75,7 +75,7 @@ module.exports = generators.Base.extend({ name: 'appDesc', message: 'What is your app description?', validate: function(input) { - if (input == null || input == "") { + if (input === null || input === "") { return "App description is required"; } else { return true; @@ -118,7 +118,7 @@ module.exports = generators.Base.extend({ if(process.env.OMRS_OWA_BASE_URL) { return process.env.OMRS_OWA_BASE_URL.endsWith(path.sep) ? process.env.OMRS_OWA_BASE_URL + suffix : process.env.OMRS_OWA_BASE_URL + path.sep + suffix; } else { - if(answers.deployType == 'standalone') { + if(answers.deployType === 'standalone') { return 'http://localhost:8081/openmrs-standalone/' + suffix; } else { return 'http://localhost:8080/openmrs/' + suffix; @@ -167,11 +167,13 @@ module.exports = generators.Base.extend({ }, writing: { - gulpfile: function() { + webpack: function() { this.fs.copyTpl( - this.templatePath('gulpfile.js'), - this.destinationPath('gulpfile.js'), + this.templatePath('webpack.config.js'), + this.destinationPath('webpack.config.js'), { + includeJQuery: this.includeJQuery, + includeAngular: this.includeAngular, date: (new Date).toISOString().split('T')[0], name: this.pkg.name, version: this.pkg.version, @@ -200,6 +202,8 @@ module.exports = generators.Base.extend({ this.templatePath('_package.json'), this.destinationPath('package.json'), { + includeJQuery: this.includeJQuery, + includeAngular: this.includeAngular, appId: 'openmrs-owa-' + this.appName.toLowerCase().replace(/\s+/g, ""), appDesc: this.appDesc, devName: this.devName, @@ -208,40 +212,6 @@ module.exports = generators.Base.extend({ ); }, - bower: function() { - var bowerJson = { - name: this.appName.toLowerCase().replace(/\s+/g, ""), - authors: [], - description: this.appDesc, - license: "MPL-2.0", - private: true, - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests" - ], - dependencies: {} - }; - - bowerJson.authors.push(this.devName); - - if (this.includeJQuery) { - bowerJson.dependencies['jquery'] = '~2.2.0'; - } - - if (this.includeAngular) { - bowerJson.dependencies['angular'] = '~1.4.9'; - } - - this.fs.writeJSON('bower.json', bowerJson); - this.fs.copy( - this.templatePath('bowerrc'), - this.destinationPath('.bowerrc') - ); - }, - git: function() { this.fs.copyTpl( this.templatePath('gitignore'), @@ -280,11 +250,11 @@ module.exports = generators.Base.extend({ images: function() { this.fs.copy( - this.templatePath('omrs-button.png'), + this.templatePath('img/omrs-button.png'), this.destinationPath('app/img/omrs-button.png') ); this.fs.copy( - this.templatePath('openmrs-with-title-small.png'), + this.templatePath('img/openmrs-with-title-small.png'), this.destinationPath('app/img/openmrs-with-title-small.png') ); }, @@ -312,7 +282,8 @@ module.exports = generators.Base.extend({ install: function() { this.installDependencies({ - skipInstall: this.options['skip-install'] + skipInstall: this.options['skip-install'], + bower: false }); }, }); diff --git a/app/templates/README.md b/app/templates/README.md index e09a3ca..5e77ad9 100644 --- a/app/templates/README.md +++ b/app/templates/README.md @@ -13,24 +13,18 @@ For further documentation about OpenMRS Open Web Apps see ### Production Build -You will need NodeJS 4+ installed to do this. See the install instructions -[here](https://nodejs.org/en/download/package-manager/). +You will need NodeJS 4+ installed to do this. See the install instructions [here](https://nodejs.org/en/download/package-manager/). -Once you have NodeJS installed, you need to install Gulp and Bower (first time - only) as follows: -```` -npm install -g gulp bower -```` +Once you have NodeJS installed, install the dependencies (first time only): -Install the dependencies (first time only): - -``` -npm install && bower install +```sh +npm install ``` -Build the distributable using [Gulp](http://gulpjs.com/) as follows: -```` -gulp +Build the distributable using [Webpack](https://webpack.github.io/) as follows: + +````sh +npm run build:prod ```` This will create a file called `<%= appId %>.zip` file in the `dist` directory, @@ -41,7 +35,7 @@ which can be uploaded to the OpenMRS Open Web Apps module. To deploy directly to your local Open Web Apps directory, run: ```` -gulp deploy-local +npm run build:deploy ```` This will build and deploy the app to the `<%= localDeployDirectory %>` @@ -70,25 +64,36 @@ will need the `APP_ENTRY_POINT` entry in your `config.json` file: Run Browsersync as follows: ``` -gulp watch +npm run watch ``` ### Extending -Install [Bower](http://bower.io/) packages dependencies as follows: +Install [npm](http://npmjs.com/) packages dependencies as follows: -```` -bower install --save +````sh +npm install --save ```` -Be sure to include the following in your `html` files at the position you want -the Bower dependencies injected: +To use the installed package, import it as follows: +````js +//import and assign to variable +import variableName from 'package'; ```` - - + +To contain package in vendor bundle, remember to add it to vendor entry point array, eg.: + +````js +entry: { + app : `${__dirname}/app/js/owa.js`, + css: `${__dirname}/app/css/owa.css`, + vendor : [ + 'package', + ...//other packages in vendor bundle + ] +}, ```` -Do the same for your Bower stylesheet dependencies, but replace `js` with `css`. Any files that you add manually must be added in the `app` directory. diff --git a/app/templates/_package.json b/app/templates/_package.json index 35f43f8..40a1b92 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -6,20 +6,40 @@ "type": "git", "url": "<%= githubRepo %>" }, - "dependencies": {}, + "dependencies": { + <% if(includeJQuery === true) { %> "jquery": "^2.2.0" <% } %> + <% if(includeAngular === true) { %> "angular": "^1.5.3" <% } %> + }, "devDependencies": { + "bestzip": "^1.1.3", + "babel-core": "^6.2.1", + "babel-loader": "^6.2.0", + "babel-preset-es2015": "^6.1.18", "browser-sync": "^2.11.1", + "browser-sync-webpack-plugin": "^1.0.1", + "copy-webpack-plugin": "^1.1.1", + "css-loader": "^0.23.1", "del": "^2.2.0", - "gulp": "^3.9.0", - "gulp-load-plugins": "^1.2.0", - "gulp-util": "^3.0.7", - "gulp-watch": "^4.3.5", - "gulp-zip": "^3.0.2", - "main-bower-files": "^2.11.1", - "wiredep": "^3.0.0" + "extract-text-webpack-plugin": "^1.0.1", + "file-loader": "^0.8.5", + "html-loader": "^0.4.3", + "html-webpack-plugin": "^2.7.1", + "raw-loader": "^0.5.1", + "rimraf": "^2.5.2", + "style-loader": "^0.13.1", + "url-loader": "^0.5.7", + "webpack": "^1.12.13", + "yargs": "^4.3.1" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "clean": "rimraf dist && rimraf coverage*", + "build": "npm run clean && webpack --progress --colors --mode=production --target=web", + "build:dev": "npm run clean && webpack --progress --colors --mode=dev --target=web", + "build:prod": "npm run test && npm run build && npm run zip", + "build:deploy": "webpack --progress --colors --mode=deploy --target=web", + "watch": "webpack --progress --colors --watch --mode=deploy --target=web", + "test": "echo \"Error: no test specified\" && exit 1", + "zip": "bestzip <%= appId %>.zip dist/*" }, "keywords": [ "OpenMRS", diff --git a/app/templates/bowerrc b/app/templates/bowerrc deleted file mode 100644 index 69fad35..0000000 --- a/app/templates/bowerrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "directory": "bower_components" -} diff --git a/app/templates/gulpfile.js b/app/templates/gulpfile.js deleted file mode 100644 index e8b6d8a..0000000 --- a/app/templates/gulpfile.js +++ /dev/null @@ -1,135 +0,0 @@ -/** - * The contents of this file are subject to the OpenMRS Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://license.openmrs.org - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - * License for the specific language governing rights and limitations - * under the License. - * Copyright (C) OpenMRS, LLC. All Rights Reserved. - */ -// generated on <%= date %> using <%= name %> <%= version %> -'use strict'; - -var fs = require('fs'); -var gulp = require('gulp'); -var gulpLoadPlugins = require('gulp-load-plugins'); -var del = require('del'); -var mainBowerFiles = require('main-bower-files'); -var wiredep = require('wiredep').stream; -var gutil = require('gulp-util'); -var browserSync = require('browser-sync').create(); - -var plugins = gulpLoadPlugins(); - -var THIS_APP_ID = '<%= appId %>'; - -var htmlGlob = ['app/**/*.html']; -var resourcesGlob = ['app/**/*.{png,svg,jpg,gif}', 'app/**/*.{css,less}', - 'app/**/*.js', 'app/manifest.webapp', /* list extra resources here */ ]; - -var getConfig = function () { - var config; - - try { - // look for config file - config = require('./config.json'); - } catch (err) { - // create file with defaults if not found - config = { - 'LOCAL_OWA_FOLDER': '<%= localDeployDirectory %>', - 'APP_ENTRY_POINT': '<%= appEntryPoint %>' - }; - - fs.writeFile('config.json', JSON.stringify(config), function(err) { - if(err) { - return gutil.log(err); - } - gutil.log("Default config file created"); - }); - - } finally { - return config; - } -} - -gulp.task('copy-bower-packages', function() { - try { - fs.statSync('bower_components'); - - return gulp.src(mainBowerFiles(), { - base: 'bower_components' - }).pipe(gulp.dest('dist/lib')); - } catch (err) { - // Don't panic - } -}); - -gulp.task('html', ['copy-bower-packages'], function() { - try { - fs.statSync('bower_components'); - - // User wiredep to automagically link bower packages - return gulp.src(htmlGlob).pipe(wiredep({ - ignorePath: '../bower_components/', - fileTypes: { - html: { - replace: { - js: '', - css: '' - } - } - } - })).pipe(gulp.dest('dist')); - } catch (err) { - return gulp.src(htmlGlob) - .pipe(gulp.dest('dist')); - } -}); - -gulp.task('resources', function() { - return gulp.src(resourcesGlob) - .pipe(gulp.dest('dist')); -}); - -gulp.task('browser-sync-inject-css', ['deploy-local'], function() { - return gulp.src('app/**/*.css').pipe(browserSync.stream()); -}); - -gulp.task('browser-sync-reload', ['deploy-local'], function() { - return browserSync.reload(); -}); - -gulp.task('watch', function() { - // forget about all the error checking for now - var config = require('./config.json'); - - browserSync.init({ - proxy: { - target: config.APP_ENTRY_POINT - } - }); - - gulp.watch('app/**/*.css', ['browser-sync-inject-css']); - gulp.watch('app/**/*.{js,html}', ['browser-sync-reload']); // reload on JS or HTML changes -}); - -gulp.task('deploy-local', ['build'], function() { - var config = getConfig(); - - return gulp.src(['dist/**/*', '!*.zip']) - .pipe(gulp.dest(config.LOCAL_OWA_FOLDER + THIS_APP_ID)); -}); - -gulp.task('build', ['resources', 'html'], function() { - return gulp.src('dist/**/*') - .pipe(plugins.zip(THIS_APP_ID + '.zip')) - .pipe(gulp.dest('dist')); -}); - -gulp.task('clean', del.bind(null, ['dist'])); - -gulp.task('default', ['clean'], function() { - gulp.start('build'); -}); diff --git a/app/templates/omrs-button.png b/app/templates/img/omrs-button.png similarity index 100% rename from app/templates/omrs-button.png rename to app/templates/img/omrs-button.png diff --git a/app/templates/openmrs-with-title-small.png b/app/templates/img/openmrs-with-title-small.png similarity index 100% rename from app/templates/openmrs-with-title-small.png rename to app/templates/img/openmrs-with-title-small.png diff --git a/app/templates/index.html b/app/templates/index.html index 9775d8e..a5ce18b 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -5,10 +5,6 @@ - - - -
@@ -23,9 +19,6 @@
Replace this with the content of your app.
- - - - + diff --git a/app/templates/webpack.config.js b/app/templates/webpack.config.js new file mode 100644 index 0000000..d6cc391 --- /dev/null +++ b/app/templates/webpack.config.js @@ -0,0 +1,158 @@ +/** + * The contents of this file are subject to the OpenMRS Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://license.openmrs.org + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * Copyright (C) OpenMRS, LLC. All Rights Reserved. + */ +// generated on <%= date %> using <%= name %> <%= version %> +'use strict'; +const webpack = require('webpack'); +const path = require('path'); +const fs = require('fs'); +const env = require('yargs').argv.mode; +const target = require('yargs').argv.target; + +const UglifyPlugin = webpack.optimize.UglifyJsPlugin; +const CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin; +const DedupePlugin = webpack.optimize.DedupePlugin; + +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const BrowserSyncPlugin = require('browser-sync-webpack-plugin'); +var CopyWebpackPlugin = require('copy-webpack-plugin') + +const nodeModulesDir = path.resolve(__dirname, '../node_modules'); + +const THIS_APP_ID = '<%= appId %>'; + +var plugins = []; +const nodeModules = {}; + +let outputFile = `.bundle`; +let outputPath; + +var configJson; +let appEntryPoint; +let localOwaFolder; + +let devtool; + +var getConfig = function () { + var config; + + try { + // look for config file + config = require('./config.json'); + } catch (err) { + // create file with defaults if not found + config = { + 'LOCAL_OWA_FOLDER': '<%= localDeployDirectory %>', + 'APP_ENTRY_POINT': '<%= appEntryPoint %>' + }; + + fs.writeFile('config.json', JSON.stringify(config)); + + } finally { + return config; + }; + } +var config = getConfig(); + +/** Minify for production */ +if (env === 'production') { + plugins.push(new UglifyPlugin({ + output: { + comments: false, + }, + minimize: true, + sourceMap: false, + compress: { + warnings: false + } + })); + plugins.push(new DedupePlugin()); + outputFile = `${outputFile}.min.js`; + outputPath = `${__dirname}/dist/`; + +} else if (env === 'deploy') { + outputFile = `${outputFile}.js`; + outputPath = `${config.LOCAL_OWA_FOLDER}${THIS_APP_ID}`; + devtool = 'source-map'; + +} else if (env === 'dev') { + outputFile = `${outputFile}.js`; + outputPath = `${__dirname}/dist/`; + devtool = 'source-map'; +} + +plugins.push(new BrowserSyncPlugin({ + proxy: { + target : config.APP_ENTRY_POINT + } +})); + +plugins.push(new CommonsChunkPlugin("vendor", "vendor.bundle.js")); + +plugins.push(new HtmlWebpackPlugin({ + template: './app/index.html', + inject: 'body' +})); + +plugins.push(new CopyWebpackPlugin([{ + from: './app/manifest.webapp' +}])); + +plugins.push(new CopyWebpackPlugin([{ + from: './app/img/omrs-button.png', + to: 'img/omrs-button.png' +}])); + +var webpackConfig = { + quiet: false, + entry: { + app : `${__dirname}/app/js/<%= appId %>.js`, + css: `${__dirname}/app/css/<%= appId %>.css`, + vendor : [ + <% if(includeJQuery === true) { %> 'jquery' <% } %> + <% if(includeAngular === true) { %> 'angular'<% } %> + ] + }, + devtool: devtool, + target, + output: { + path: outputPath, + filename: '[name]'+outputFile, + }, + module: { + loaders: [{ + test: /\.jsx?$/, + loader: 'babel-loader', + exclude: /node_modules/, + query: { + presets: ['es2015'], + cacheDirectory : true + } + },{ + test: /\.css$/, + loader: 'style-loader!css-loader' + }, { + test: /\.(png|jpg|jpeg|gif|svg)$/, + loader: 'url' + }, { + test: /\.html$/, + loader: 'html' + }], + }, + resolve: { + root: path.resolve('./src'), + extensions: ['', '.js'], + }, + plugins, + externals: nodeModules, +}; + +module.exports = webpackConfig; \ No newline at end of file diff --git a/package.json b/package.json index 796ef51..9d72ef8 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "yosay": "^1.1.0" }, "devDependencies": { - "mocha": "*", + "mocha": "^2.4.5", "object-assign": "^4.0.1", "path": "^0.12.7", "yeoman-assert": "^2.1.1", diff --git a/test/dependencies.js b/test/dependencies.js index 732eef1..9c8d539 100644 --- a/test/dependencies.js +++ b/test/dependencies.js @@ -23,10 +23,10 @@ describe('Dependencies tests', function() { it('should add selected dependecies', function() { - assert.fileContent([['bower.json', /jquery/]]); + assert.fileContent([['package.json', /jquery/]]); }); it('should not add unselected dependencies', function() { - assert.noFileContent([['bower.json', /angular/]]); + assert.noFileContent([['package.json', /angular/]]); }); }); diff --git a/test/general.js b/test/general.js index e2d72ef..778fee0 100644 --- a/test/general.js +++ b/test/general.js @@ -21,7 +21,6 @@ describe('General tests', function() { it('should create the expected files', function() { assert.file([ - '.bowerrc', '.gitignore', 'app/css/omrsowa.css', 'app/img', @@ -31,8 +30,7 @@ describe('General tests', function() { 'app/js', 'app/js/omrsowa.js', 'app/manifest.webapp', - 'bower.json', - 'gulpfile.js', + 'webpack.config.js', 'LICENSE', 'package.json', 'README.md' @@ -40,22 +38,22 @@ describe('General tests', function() { }); it('should generate correct dependencies', function() { - ['del', 'gulp', 'gulp-load-plugins', 'gulp-zip', - 'main-bower-files', 'wiredep'].forEach(function(dep) { + ['bestzip', 'babel-loader', 'browser-sync', 'css-loader', + 'rimraf', 'copy-webpack-plugin'].forEach(function(dep) { assert.fileContent([['package.json', dep]]); }); }); it('should correctly populate author', function() { - ['bower.json', 'package.json'].forEach(function(fileName) { + ['package.json'].forEach(function(fileName) { assert.fileContent([[fileName, /omrsuser/]]); }); }); - it('should generate expected gulp tasks', function() { - ['copy-bower-packages', 'html', 'resources', 'deploy-local', - 'build', 'clean', 'default'].forEach(function(task) { - assert.fileContent([['gulpfile.js', task]]); + it('should generate expected npm scripts', function() { + ['clean', 'build', 'build:prod', 'build:deploy', + 'watch', 'test', 'zip'].forEach(function(task) { + assert.fileContent([['package.json', task]]); }); }); }); From eb6d583c7a9f81c65a501af75fda10db1ad57582 Mon Sep 17 00:00:00 2001 From: PawelGutkowski Date: Wed, 11 May 2016 09:37:14 +0200 Subject: [PATCH 2/2] RA-1121 use archiver to create distributable zip --- app/index.js | 2 +- app/templates/_package.json | 10 +++++----- app/templates/webpack.config.js | 24 +++++++++++++++++++++++- test/general.js | 4 ++-- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/app/index.js b/app/index.js index 545c601..c6313d7 100644 --- a/app/index.js +++ b/app/index.js @@ -204,7 +204,7 @@ module.exports = generators.Base.extend({ { includeJQuery: this.includeJQuery, includeAngular: this.includeAngular, - appId: 'openmrs-owa-' + this.appName.toLowerCase().replace(/\s+/g, ""), + appId: this.appName.toLowerCase().replace(/\s+/g, ""), appDesc: this.appDesc, devName: this.devName, githubRepo: this.githubRep diff --git a/app/templates/_package.json b/app/templates/_package.json index 40a1b92..2046e30 100644 --- a/app/templates/_package.json +++ b/app/templates/_package.json @@ -11,7 +11,6 @@ <% if(includeAngular === true) { %> "angular": "^1.5.3" <% } %> }, "devDependencies": { - "bestzip": "^1.1.3", "babel-core": "^6.2.1", "babel-loader": "^6.2.0", "babel-preset-es2015": "^6.1.18", @@ -29,17 +28,18 @@ "style-loader": "^0.13.1", "url-loader": "^0.5.7", "webpack": "^1.12.13", - "yargs": "^4.3.1" + "yargs": "^4.3.1", + "archiver": "^1.0.0", + "on-build-webpack": "^0.1.0" }, "scripts": { "clean": "rimraf dist && rimraf coverage*", "build": "npm run clean && webpack --progress --colors --mode=production --target=web", "build:dev": "npm run clean && webpack --progress --colors --mode=dev --target=web", - "build:prod": "npm run test && npm run build && npm run zip", + "build:prod": "npm run test && npm run build", "build:deploy": "webpack --progress --colors --mode=deploy --target=web", "watch": "webpack --progress --colors --watch --mode=deploy --target=web", - "test": "echo \"Error: no test specified\" && exit 1", - "zip": "bestzip <%= appId %>.zip dist/*" + "test": "echo \"Error: no test specified\"" }, "keywords": [ "OpenMRS", diff --git a/app/templates/webpack.config.js b/app/templates/webpack.config.js index d6cc391..96ab4ce 100644 --- a/app/templates/webpack.config.js +++ b/app/templates/webpack.config.js @@ -23,7 +23,8 @@ const DedupePlugin = webpack.optimize.DedupePlugin; const HtmlWebpackPlugin = require('html-webpack-plugin'); const BrowserSyncPlugin = require('browser-sync-webpack-plugin'); -var CopyWebpackPlugin = require('copy-webpack-plugin') +const CopyWebpackPlugin = require('copy-webpack-plugin') +const WebpackOnBuildPlugin = require('on-build-webpack'); const nodeModulesDir = path.resolve(__dirname, '../node_modules'); @@ -77,6 +78,27 @@ if (env === 'production') { plugins.push(new DedupePlugin()); outputFile = `${outputFile}.min.js`; outputPath = `${__dirname}/dist/`; + plugins.push(new WebpackOnBuildPlugin(function(stats){ + //create zip file + var archiver = require('archiver'); + var pjson = require('./package.json'); + var output = fs.createWriteStream(THIS_APP_ID+"-v"+pjson.version+'.zip'); + var archive = archiver('zip') + + output.on('close', function () { + console.log('distributable has been zipped! size: '+archive.pointer()); + }); + + archive.on('error', function(err){ + throw err; + }); + + archive.pipe(output); + archive.bulk([ + { expand: true, cwd: 'dist/', src: ['**']} + ]); + archive.finalize(); + })) } else if (env === 'deploy') { outputFile = `${outputFile}.js`; diff --git a/test/general.js b/test/general.js index 778fee0..1adab01 100644 --- a/test/general.js +++ b/test/general.js @@ -38,7 +38,7 @@ describe('General tests', function() { }); it('should generate correct dependencies', function() { - ['bestzip', 'babel-loader', 'browser-sync', 'css-loader', + ['babel-loader', 'browser-sync', 'css-loader', 'rimraf', 'copy-webpack-plugin'].forEach(function(dep) { assert.fileContent([['package.json', dep]]); }); @@ -52,7 +52,7 @@ describe('General tests', function() { it('should generate expected npm scripts', function() { ['clean', 'build', 'build:prod', 'build:deploy', - 'watch', 'test', 'zip'].forEach(function(task) { + 'watch', 'test'].forEach(function(task) { assert.fileContent([['package.json', task]]); }); });