diff --git a/package.json b/package.json index 5300400..0492ded 100644 --- a/package.json +++ b/package.json @@ -12,13 +12,14 @@ "author": "BigchainDB", "main": "./dist/node/index.js", "browser": "./dist/browser/bigchaindb-driver.cjs2.min.js", + "sideEffects": false, "scripts": { "lint": "eslint ./{src,test,examples}/**/*.js", "build": "npm run clean && npm run build:cjs && npm run build:dist", "build:bundle": "webpack", "build:cjs": "cross-env BABEL_ENV=cjs babel ./src -d dist/node", - "build:dist": "cross-env NODE_ENV=production webpack -p", - "dev": "webpack -p -w", + "build:dist": "cross-env NODE_ENV=production webpack", + "dev": "webpack -w", "clean": "rimraf dist/bundle dist/node", "test": "npm run lint && nyc ava test/ && npm run thanks && npm run report-coverage", "thanks": "cowsay Hi, thanks for your interest in BigchainDB. We appreciate your contribution!", @@ -61,7 +62,8 @@ "rimraf": "^2.6.2", "sinon": "^6.1.0", "webpack": "^4.16.1", - "webpack-cli": "^3.0.8" + "webpack-cli": "^3.0.8", + "webpack-concat-plugin": "^3.0.0" }, "dependencies": { "browser-resolve": "^1.11.3", @@ -79,7 +81,10 @@ "json-stable-stringify": "^1.0.1", "query-string": "^6.0.0", "sprintf-js": "^1.1.1", - "tweetnacl": "^1.0.0" + "tweetnacl": "^1.0.0", + "uglifyjs-webpack-plugin": "^1.2.7", + "webpack-merge": "^4.1.3", + "webpack-sources": "^1.1.0" }, "keywords": [ "bigchaindb", diff --git a/plugins/add-vendors-plugin.js b/plugins/add-vendors-plugin.js new file mode 100644 index 0000000..be75bcd --- /dev/null +++ b/plugins/add-vendors-plugin.js @@ -0,0 +1,31 @@ +const { ConcatSource } = require('webpack-sources') + +module.exports = class AddVendorsPlugin { + constructor(base) { + this.base = base + } + + apply(compiler) { + compiler.hooks.emit.tapAsync( + `AddVendorsPlugin ${this.base}`, + (compilation, callback) => { + const main = compilation.assets[`main.${this.base}`] + const mainMap = compilation.assets[`main.${this.base}.map`] + const vendor = compilation.assets[`vendors.${this.base}`] + + if (main && vendor) { + const compiledAsset = new ConcatSource(main.children[0]) + compiledAsset.add(vendor) + compiledAsset.add(main.children[1]) + compilation.assets = {} + compilation.assets[this.base] = compiledAsset + } else if (main && mainMap) { + compilation.assets = {} + compilation.assets[this.base] = main + compilation.assets[`${this.base}.map`] = mainMap + } + callback() + } + ) + } +} diff --git a/webpack.common.js b/webpack.common.js new file mode 100644 index 0000000..eb2795c --- /dev/null +++ b/webpack.common.js @@ -0,0 +1,29 @@ +/* eslint-disable strict, no-console, object-shorthand */ + +'use strict' + +const { paths } = require('./webpack.parts.js') + +module.exports = { + entry: paths.entry, + mode: 'none', + module: { + rules: [ + { + test: /\.js$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader', + }, + } + ] + }, + optimization: { + minimize: true, + noEmitOnErrors: true + }, + resolve: { + extensions: ['.js'], + modules: ['node_modules'], + }, +} diff --git a/webpack.config.js b/webpack.config.js index b7d1ad5..384f0ec 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -2,112 +2,29 @@ 'use strict' -const path = require('path') - -const webpack = require('webpack') - const PRODUCTION = process.env.NODE_ENV === 'production' -const PATHS = { - ENTRY: path.resolve(__dirname, './src/index.js'), - BUNDLE: path.resolve(__dirname, 'dist/browser'), - NODE_MODULES: path.resolve(__dirname, 'node_modules'), +const common = require('./webpack.common.js') + +const { outputs } = require('./webpack.parts.js') + +// '[libraryTarget]': [file extension] +const OUTPUT_MAPPING = { + 'amd': 'amd', + 'commonjs': 'cjs', + 'commonjs2': 'cjs2', + 'umd': 'umd', + 'window': 'window', } -const OUTPUTS = [ - { - filename: PRODUCTION ? 'bigchaindb-driver.window.min.js' : 'bigchaindb-driver.window.js', - library: 'BigchainDB', - libraryTarget: 'window', - path: PATHS.BUNDLE, - }, - { - filename: PRODUCTION ? 'bigchaindb-driver.umd.min.js' : 'bigchaindb-driver.umd.js', - library: 'bigchaindb-driver', - libraryTarget: 'umd', - path: PATHS.BUNDLE, - }, - { - filename: PRODUCTION ? 'bigchaindb-driver.cjs.min.js' : 'bigchaindb-driver.cjs.js', - library: 'bigchaindb-driver', - libraryTarget: 'commonjs', - path: PATHS.BUNDLE, - }, - { - filename: PRODUCTION ? 'bigchaindb-driver.cjs2.min.js' : 'bigchaindb-driver.cjs2.js', - library: 'bigchaindb-driver', - libraryTarget: 'commonjs2', - path: PATHS.BUNDLE, - }, - { - filename: PRODUCTION ? 'bigchaindb-driver.amd.min.js' : 'bigchaindb-driver.amd.js', - library: 'bigchaindb-driver', - libraryTarget: 'amd', - path: PATHS.BUNDLE, - } -] - - -/** PLUGINS **/ -const PLUGINS = [ - new webpack.NoEmitOnErrorsPlugin(), -] - -const PROD_PLUGINS = [ - /* - new webpack.optimize.UglifyJsPlugin({ - compress: { - warnings: false, - }, - output: { - comments: false, - }, - sourceMap: true, - }), - new webpack.LoaderOptionsPlugin({ - debug: false, - minimize: true, - }), - */ -] +const OVERRIDES = { + // optimization: { + // minimize: false + // } +} if (PRODUCTION) { - PLUGINS.push(...PROD_PLUGINS) + module.exports = outputs(common, 'production', OUTPUT_MAPPING, OVERRIDES) +} else { + module.exports = outputs(common, 'development', OUTPUT_MAPPING, OVERRIDES) } - -const configBoilerplate = { - entry: [PATHS.ENTRY], - - devtool: PRODUCTION ? '#source-map' : '#inline-source-map', - - resolve: { - extensions: ['.js'], - modules: ['node_modules'], // Don't use absolute path here to allow recursive matching - }, - - plugins: PLUGINS, - - module: { - rules: [ - { - test: /\.js$/, - exclude: [PATHS.NODE_MODULES], - use: [{ - loader: 'babel-loader', - options: { - cacheDirectory: true, - }, - }], - }, - ], - }, -} - -/** EXPORTED WEBPACK CONFIG **/ -const config = OUTPUTS.map(output => { - const configCopy = Object.assign({}, configBoilerplate) - configCopy.output = output - return configCopy -}) - -module.exports = config diff --git a/webpack.development.js b/webpack.development.js new file mode 100644 index 0000000..c383594 --- /dev/null +++ b/webpack.development.js @@ -0,0 +1,30 @@ +/* eslint-disable strict, no-console, object-shorthand */ + +'use strict' + +const UglifyJsPlugin = require('uglifyjs-webpack-plugin') + +module.exports = { + devtool: 'inline-source-map', + optimization: { + minimizer: [ + new UglifyJsPlugin({ + test: /vendor/, + sourceMap: false, + }), + new UglifyJsPlugin({ + test: /^((?!(vendor)).)*.js$/, + sourceMap: true, + }) + ], + splitChunks: { + cacheGroups: { + commons: { + test: /[\\/]node_modules[\\/]/, + name: 'vendors', + chunks: 'all' + } + } + }, + }, +} diff --git a/webpack.parts.js b/webpack.parts.js new file mode 100644 index 0000000..89606f7 --- /dev/null +++ b/webpack.parts.js @@ -0,0 +1,55 @@ +/* eslint-disable strict, no-console, object-shorthand */ + +'use strict' + +const path = require('path') +const merge = require('webpack-merge') + +const development = require('./webpack.development.js') +const production = require('./webpack.production.js') + +const AddVendorsPlugin = require('./plugins/add-vendors-plugin') + +const paths = { + entry: path.resolve(__dirname, './src/index.js'), + bundle: path.resolve(__dirname, 'dist/browser'), +} + +const outputs = (base, env, mapping, overrides) => { + const collection = [] + const library = 'bigchaindb-driver' + const windowLibrary = 'BigchainDB' + + let environment = development + let ext = 'js' + + if (env === 'production') { + environment = production + ext = `min.${ext}` + } + + Object.entries(mapping).forEach(([target, extension]) => { + const filename = `[name].${library}.${extension}.${ext}` + + const compiled = { + output: { + filename: filename, + library: target === 'window' ? windowLibrary : library, + libraryTarget: target, + path: paths.bundle + }, + plugins: [ + new AddVendorsPlugin(`${library}.${extension}.${ext}`) + ] + } + + collection.push(merge(base, environment, compiled, overrides)) + }) + + return collection +} + +module.exports = { + outputs, + paths +} diff --git a/webpack.production.js b/webpack.production.js new file mode 100644 index 0000000..368a93d --- /dev/null +++ b/webpack.production.js @@ -0,0 +1,7 @@ +/* eslint-disable strict, no-console, object-shorthand */ + +'use strict' + +module.exports = { + devtool: 'source-map', +}