Skip to content

Instantly share code, notes, and snippets.

@DanielaValero
Created April 24, 2017 09:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DanielaValero/b57b48d942adb30cae470170e9c4ba85 to your computer and use it in GitHub Desktop.
Save DanielaValero/b57b48d942adb30cae470170e9c4ba85 to your computer and use it in GitHub Desktop.
/* ==========================================================================
Create the bundles
========================================================================== */
import gutil from 'gulp-util';
import webpack from 'webpack';
import webpackConfig from '../config/webpack.config';
function bundle(options) {
const compiler = webpack(webpackConfig(options));
return (callback) => {
compiler.run((err, stats) => {
if (err) {
throw new gutil.PluginError('webpack', err);
}
if (stats.hasErrors()) {
stats.toJson().errors.forEach(error =>
gutil.log(gutil.colors.red(`[webpack] ${error}`)));
}
if (stats.hasWarnings()) {
stats.toJson().warnings.forEach(warning =>
gutil.log(gutil.colors.yellow(`[webpack] ${warning}`)));
}
callback();
});
};
}
function dev() {
return bundle({
development: true,
environment: 'development',
});
}
function dist() {
return bundle({
environment: 'production',
});
}
function styleguide() {
return bundle({
styleguide: true,
development: true,
environment: 'styleguide',
});
}
export default {
dev,
dist,
styleguide,
};
/* eslint-disable strict */
// Karma runs with node, which needs the use strict flag
// to use const, let, etc. Therefore disabling it here
'use strict';
/* eslint-enable strict */
const webpack = require('webpack');
const path = require('path');
const CompressionPlugin = require('compression-webpack-plugin');
const saveLicense = require('uglify-save-license');
const platformConfig = require('./platform.config.js');
const paths = platformConfig.paths;
/* ==========================================================================
General configs
========================================================================== */
const output = {
path: paths.dist,
publicPath: '/',
filename: '[name].js',
chunkFilename: '[name].chunk.js',
};
const modules = [
paths.src,
paths.nodeModules,
path.resolve(__dirname, './'),
];
const compression = {
asset: '[path].gz[query]',
algorithm: 'gzip',
test: /\.js$/,
threshold: 10240,
minRatio: 0.8,
};
/* ==========================================================================
Module loaders definition
========================================================================== */
function defineRules(isTesting) {
const rules = [{
test: /modernizr\.config(\.js)?$/,
loader: 'modernizr-loader',
}, {
test: /\.js$/,
exclude: /(node_modules)/,
include: paths.src,
loaders: ['ng-annotate-loader', 'babel-loader'],
}, {
test: /\.html$/,
use: ['raw-loader', 'html-minify-loader'],
}, {
test: /\.jpg/,
loader: 'url-loader',
options: {
limit: 'limit=10000',
mimetype: 'image/jpg',
},
}, {
test: /\.gif/,
loader: 'url-loader',
options: {
limit: 'limit=10000',
mimetype: 'image/gif',
},
}, {
test: /\.png/,
loader: 'url-loader',
options: {
limit: 'limit=10000',
mimetype: 'image/png',
},
}, {
test: /\.svg/,
loader: 'url-loader',
options: {
limit: 'limit=10000',
mimetype: 'image/svg',
},
}, {
test: /\.(woff|woff2|eot|ttf|svg)$/,
loader: 'file-loader',
options: {
limit: 'limit=10000',
name: 'fonts/[name].[ext]',
},
}, {
test: /\.(pdf|txt)$/,
loader: 'file-loader',
options: {
limit: 'limit=10000',
name: 'files/[name].[ext]',
},
},
];
if (isTesting) {
// Adds the babel loader to
// body builder, so phantomJS gets the es2015 feats working
rules.push({
test: /\.js$/,
include: `${paths.nodeModules}/bodybuilder/`,
loaders: ['babel-loader'],
});
// Loads js files with isparta (files will be automatically transpiled)
rules.push({
test: /\.js$/,
loader: 'istanbul-instrumenter-loader',
options: {
esModules: true,
produceSourceMap: true,
},
enforce: 'pre',
exclude: /(test|node_modules|config|\.spec\.js|\.directive\.js)/,
include: platformConfig.paths.src,
});
}
return rules;
}
/* ==========================================================================
Entry points definition
========================================================================== */
function defineEntry(isDevelopment, isStyleguide) {
const appScript = [`${paths.src}/core/scripts/${paths.main}`];
// When we use webpack, and we import a library in the code
// webpack will automatically add it to the bundle.
// However, we want to deliver two bundles, vendor and main.
// In order to do so, we need to clearly tell webpack, what is
// vendor and what is main. For that, we declare them here.
const angularLibs = [
`${paths.nodeModules}/angular/angular.js`,
`${paths.nodeModules}/angularjs-slider/dist/rzslider.min.js`,
`${paths.nodeModules}/angular-animate/angular-animate.js`,
`${paths.nodeModules}/angular-cookies/angular-cookies.js`,
`${paths.nodeModules}/angular-recaptcha/release/angular-recaptcha.js`,
`${paths.nodeModules}/angular-touch/angular-touch.js`,
`${paths.nodeModules}/angular-sanitize/angular-sanitize.js`,
`${paths.nodeModules}/angular-messages/angular-messages.js`,
`${paths.nodeModules}/angular-elastic/elastic.js`,
`${paths.nodeModules}/angular-svg-base-fix/src/svgBaseFix.js`,
'ng-dialog',
];
// These libraries are not related to angular, these are polyfill that,
// when loaded in the page, they will be automatically executed
// generating the polyfill for whatever feature they are targeting to.
// We split them in a separate array, so we have the posibility to
// add them to the styleguide, and also load them quicker if it is
// required.
const vendor = [
`${paths.nodeModules}/picturefill/dist/picturefill.min.js`,
`${paths.nodeModules}/picturefill/dist/plugins/mutation/pf.mutation.min.js`,
`${paths.nodeModules}/lazysizes/lazysizes.min.js`,
`${paths.nodeModules}/fontfaceobserver/fontfaceobserver.js`,
`${paths.nodeModules}/raf.js/raf.js`,
];
if (isDevelopment) {
vendor.push('eventsource-polyfill');
}
// Used for IE in prod.
vendor.push('babel-polyfill');
let entry;
if (!isStyleguide) {
entry = {
'scripts/main': appScript,
'scripts/vendor': vendor.concat(angularLibs),
};
} else {
entry = {
'styleguide/scripts/main': appScript,
'styleguide/scripts/vendor': vendor,
};
}
return entry;
}
/* ==========================================================================
Plugins definition
========================================================================== */
function definePlugins(options) {
// More info about the webpack plugins here:
// https://github.com/webpack/docs/wiki/optimization
const plugins = [
// Avoid publishing files when compilation failed
new webpack.NoEmitOnErrorsPlugin(),
new webpack.LoaderOptionsPlugin({
debug: options.development,
compress: true,
options: {
'html-minify-loader': {
// See possible options here:
// https://github.com/kangax/html-minifier#options-quick-reference
// And a recommendation for angular templates here:
// https://www.npmjs.com/package/grunt-angular-templates#htmlmin
collapseBooleanAttributes: true,
collapseWhitespace: true,
conservativeCollapse: true,
removeAttributeQuotes: true,
removeComments: true,
removeEmptyAttributes: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
},
},
}),
];
// Split the vendor dependencies into a separate file
if (!options.styleguide) {
plugins.push(new webpack.optimize.CommonsChunkPlugin({
name: 'scripts/vendor',
minChunks: Infinity,
}));
}
if (options.development) {
// Tell webpack we want hot reloading
plugins.push(new webpack.HotModuleReplacementPlugin());
}
if (options.environment) {
plugins.push(new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(options.environment),
},
}));
}
if (!(options.development || options.testing)) {
plugins.push(new webpack.optimize.UglifyJsPlugin({
output: {
comments: saveLicense,
},
// skip pre-minified libs
exclude: [/\.min\.js$/gi],
mangle: {
// You can specify all variables that should not be mangled.
// For example if your vendor dependency doesn't use modules
// and relies on global variables. Most of angular modules relies on
// angular global variable, so we should keep it unchanged
except: ['$super', '$', 'exports', 'require', 'angular'],
},
}));
plugins.push(new webpack.LoaderOptionsPlugin({
minimize: true,
}));
plugins.push(new webpack.BannerPlugin({
banner: `/**\n* Robert Bosch GmbH, ${new Date().getFullYear()}\n*/`,
raw: true,
entryOnly: true,
}));
}
// Add Compression Plugin
plugins.push(new CompressionPlugin(compression));
return plugins;
}
/**
* Creates the default configuration of webpack.
* It receives an object with parameters changing depending
* on the environment webpack needs to run.
* @param {object} options Object of parameters
* @param {boolean} options.development true if you want to have a development build
* @param {boolean} options.testing True if you are running the tests
* @param {boolean} options.styleguide True if the bundle is for the living styleguide
* @param {string} options.environment The environment (for bundling defines)
* @return {object} Object of config settings
*/
function webpackConfig(options) {
const testingPlugins = [];
const isNotProduction = (options.development || options.testing);
const plugins = (!options.testing) ? definePlugins(options) : testingPlugins;
const entry = defineEntry(isNotProduction, options.styleguide);
const rules = defineRules(options.testing);
const config = {
// For more info about this:
// http://webpack.github.io/docs/configuration.html
entry,
output,
watch: isNotProduction,
// Cache generated modules and chunks to
// improve performance for multiple incremental builds.
cache: isNotProduction,
// http://webpack.github.io/docs/configuration.html#devtool
devtool: isNotProduction ? '#inline-source-map' : false,
module: {
rules,
noParse: [
/(node_modules|~)\/(min\.|jquery)\//gi,
],
},
resolve: {
modules,
},
plugins,
};
return config;
}
module.exports = webpackConfig;
/* eslint-disable strict */
// Karma runs with node, which needs the use strict flag
// to use const, let, etc. Therefore disabling it here
'use strict';
/* eslint-enable strict */
const webpackConfig = require('./webpack.config.js');
const developmentSettings = {
// Options to send to our webpack config
// so we set the right settings
testing: true,
environment: 'testing',
reporters: ['mocha', 'coverage-istanbul'],
};
module.exports = webpackConfig(developmentSettings);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment