webpack.external.js
const pkg = require('./package.json');
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const StyleLintPlugin = require('stylelint-webpack-plugin');
const customLoader = require('custom-loader');
const archiver = require('archiver');
const extractSrc = new MiniCssExtractPlugin({
filename: "vizabi.css"
});
const __PROD__ = process.env.NODE_ENV === 'production';
const timestamp = new Date();
const stats = {
colors: true,
hash: false,
version: false,
timings: true,
assets: false,
chunks: false,
modules: false,
reasons: true,
children: false,
source: false,
errors: true,
errorDetails: true,
warnings: true,
publicPath: false
};
function AfterBuildPlugin(callback) {
this.callback = callback;
}
AfterBuildPlugin.prototype.apply = function(compiler) {
compiler.hooks.done.tap('AfterBuildPlugin', this.callback);
};
customLoader.loaders = {
['config-loader'](source) {
this.cacheable && this.cacheable();
const value = typeof source === 'string' ? JSON.parse(source) : source;
this.value = [value];
return `var VIZABI_MODEL = ${JSON.stringify(value, undefined, ' ')};`;
}
};
const rules = [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: !__PROD__,
presets: ['env']
}
}
]
},
{
test: /\.scss$/,
include: [
path.resolve(__dirname, 'src')
],
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
minimize: __PROD__,
sourceMap: true
}
},
{
loader: 'postcss-loader'
},
{
loader: 'sass-loader',
options: {
implementation: require("sass")
}
}
]
},
{
test: /\.cur$/,
loader: 'file-loader',
options: {
publicPath: path => path.split('/').slice(1).join('/'),
name: 'preview/assets/cursors/[name].[ext]'
}
},
{
test: /\.html$/,
include: [path.resolve(__dirname, 'src')],
loader: 'html-loader'
},
];
module.exports = output => {
const plugins = [
new CleanWebpackPlugin(['build']),
extractSrc,
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, 'src', 'assets', 'translation'),
to: path.resolve(output || path.resolve(__dirname, 'build'), 'assets', 'translation'),
}
]),
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, 'src', 'assets', 'cursors'),
to: path.resolve(output || path.resolve(__dirname, 'build'), 'assets', 'cursors')
}
]),
new StyleLintPlugin({
context: path.resolve(__dirname),
configFile: path.resolve(__dirname, '.stylelintrc.yml'),
syntax: 'scss',
files: 'src/**/*.s?(a|c)ss'
}),
new webpack.DefinePlugin({
__VERSION: JSON.stringify(pkg.version),
__BUILD: +timestamp
}),
new webpack.BannerPlugin({
banner: "((function(){})({version: '" + JSON.stringify(pkg.version) + "'}));",
raw: true,
test: /\.js$/
})
];
const optimization = {};
const entry = {
'vizabi': path.resolve(__dirname, 'src', 'vizabi-gapminder'),
};
if (__PROD__) {
entry["vizabi.min"] = entry["vizabi"];
plugins.push(
new AfterBuildPlugin(() => {
const archive = archiver('zip');
const files = [
'vizabi.css',
'vizabi.min.js',
'vizabi.js'
];
files.forEach(name =>
archive.append(
fs.createReadStream(path.resolve('build', name)),
{ name }
)
);
archive.pipe(
fs.createWriteStream(path.resolve('build', 'vizabi.zip'))
);
archive.glob('**/*', { cwd: 'src/assets/cursors', dot: true }, { prefix: 'assets/cursors' });
archive.glob('en.json', { cwd: 'src/assets/translation', dot: true }, { prefix: 'assets/translation' });
archive.finalize();
})
);
optimization.minimizer = [
new UglifyJsPlugin({
include: /\.min\.js$/,
parallel: true,
sourceMap: true,
uglifyOptions: {
compress: {
warnings: false
},
mangle: {
},
output: {
comments: false,
}
}
}),
new webpack.BannerPlugin({
banner: [
'/**',
' * ' + pkg.name + ' - ' + pkg.description,
' * @version v' + pkg.version,
' * @build timestamp ' + timestamp,
' * @link ' + pkg.homepage,
' * @license ' + pkg.license,
' */',
''
].join('\n'),
raw: true
})
];
}
return {
mode: __PROD__ ? 'production': 'development',
performance: {
hints: false
},
devtool: 'source-map',
entry,
output: {
path: output || path.resolve(__dirname, 'build'),
filename: '[name].js',
devtoolNamespace: "",
library: 'Vizabi',
libraryTarget: 'umd',
umdNamedDefine: true
},
resolveLoader: {
modules: [
'web_loaders',
'web_modules',
'node_loaders',
'node_modules',
path.resolve(__dirname, 'node_modules'),
],
},
resolve: {
modules: [
path.resolve(__dirname, 'src'),
'node_modules'
]
},
module: {
rules,
},
optimization,
plugins
};
};