'use strict';
|
|
const fs = require('fs');
|
|
const glob = require('glob');
|
|
const path = require('path');
|
|
const webpack = require('webpack');
|
|
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
|
const CleanPlugin = require('clean-webpack-plugin');
|
|
const CircularDependencyPlugin = require('circular-dependency-plugin');
|
|
const HtmlInlineSourcePlugin = require('html-webpack-inline-source-plugin');
|
|
const HtmlPlugin = require('html-webpack-plugin');
|
|
const ImageminPlugin = require('imagemin-webpack-plugin').default;
|
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
const TerserPlugin = require('terser-webpack-plugin');
|
|
|
|
module.exports = function(env, argv) {
|
|
env = env || {};
|
|
env.analyzeBundle = Boolean(env.analyzeBundle);
|
|
env.analyzeDeps = Boolean(env.analyzeDeps);
|
|
env.production = env.analyzeBundle || Boolean(env.production);
|
|
env.optimizeImages = Boolean(env.optimizeImages) || (env.production && !env.analyzeBundle);
|
|
|
|
if (!env.optimizeImages && !fs.existsSync(path.resolve(__dirname, 'images/settings'))) {
|
|
env.optimizeImages = true;
|
|
}
|
|
|
|
return [getExtensionConfig(env), getUIConfig(env)];
|
|
};
|
|
|
|
function getExtensionConfig(env) {
|
|
const plugins = [new CleanPlugin(), new webpack.IgnorePlugin(/^spawn-sync$/)];
|
|
|
|
if (env.analyzeDeps) {
|
|
plugins.push(
|
|
new CircularDependencyPlugin({
|
|
cwd: __dirname,
|
|
exclude: /node_modules/,
|
|
failOnError: false,
|
|
onDetected({ module: webpackModuleRecord, paths, compilation }) {
|
|
if (paths.some(p => /container\.ts/.test(p))) return;
|
|
|
|
compilation.warnings.push(new Error(paths.join(' -> ')));
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
if (env.analyzeBundle) {
|
|
plugins.push(new BundleAnalyzerPlugin());
|
|
}
|
|
|
|
return {
|
|
name: 'extension',
|
|
entry: './src/extension.ts',
|
|
mode: env.production ? 'production' : 'development',
|
|
target: 'node',
|
|
node: {
|
|
__dirname: false
|
|
},
|
|
devtool: 'source-map',
|
|
output: {
|
|
libraryTarget: 'commonjs2',
|
|
filename: 'extension.js'
|
|
},
|
|
optimization: {
|
|
minimizer: [
|
|
new TerserPlugin({
|
|
cache: true,
|
|
parallel: true,
|
|
sourceMap: true,
|
|
terserOptions: {
|
|
ecma: 8,
|
|
// Keep the class names otherwise @log won't provide a useful name
|
|
keep_classnames: true,
|
|
module: true
|
|
}
|
|
})
|
|
]
|
|
},
|
|
externals: {
|
|
vscode: 'commonjs vscode'
|
|
},
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: /\.ts$/,
|
|
enforce: 'pre',
|
|
use: 'tslint-loader',
|
|
exclude: /node_modules/
|
|
},
|
|
{
|
|
test: /\.tsx?$/,
|
|
use: 'ts-loader',
|
|
exclude: /node_modules|\.d\.ts$/
|
|
}
|
|
],
|
|
// Removes `Critical dependency: the request of a dependency is an expression` from `./node_modules/vsls/vscode.js`
|
|
exprContextRegExp: /^$/,
|
|
exprContextCritical: false
|
|
},
|
|
resolve: {
|
|
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json']
|
|
},
|
|
plugins: plugins,
|
|
stats: {
|
|
all: false,
|
|
assets: true,
|
|
builtAt: true,
|
|
env: true,
|
|
errors: true,
|
|
timings: true,
|
|
warnings: true
|
|
}
|
|
};
|
|
}
|
|
|
|
function getUIConfig(env) {
|
|
const clean = ['settings.html', 'welcome.html'];
|
|
if (env.optimizeImages) {
|
|
console.log('Optimizing images (src/ui/images/settings/*.png)...');
|
|
clean.push('images/settings');
|
|
}
|
|
|
|
const plugins = [
|
|
new CleanPlugin({ cleanOnceBeforeBuildPatterns: clean }),
|
|
new MiniCssExtractPlugin({
|
|
filename: '[name].css'
|
|
}),
|
|
new HtmlPlugin({
|
|
excludeChunks: ['welcome'],
|
|
template: 'settings/index.html',
|
|
filename: path.resolve(__dirname, 'settings.html'),
|
|
inject: true,
|
|
inlineSource: env.production ? '.(js|css)$' : undefined,
|
|
minify: env.production
|
|
? {
|
|
removeComments: true,
|
|
collapseWhitespace: true,
|
|
removeRedundantAttributes: true,
|
|
useShortDoctype: true,
|
|
removeEmptyAttributes: true,
|
|
removeStyleLinkTypeAttributes: true,
|
|
keepClosingSlash: true,
|
|
minifyCSS: true
|
|
}
|
|
: false
|
|
}),
|
|
new HtmlPlugin({
|
|
excludeChunks: ['settings'],
|
|
template: 'welcome/index.html',
|
|
filename: path.resolve(__dirname, 'welcome.html'),
|
|
inject: true,
|
|
inlineSource: env.production ? '.(js|css)$' : undefined,
|
|
minify: env.production
|
|
? {
|
|
removeComments: true,
|
|
collapseWhitespace: true,
|
|
removeRedundantAttributes: true,
|
|
useShortDoctype: true,
|
|
removeEmptyAttributes: true,
|
|
removeStyleLinkTypeAttributes: true,
|
|
keepClosingSlash: true,
|
|
minifyCSS: true
|
|
}
|
|
: false
|
|
}),
|
|
new HtmlInlineSourcePlugin(),
|
|
new ImageminPlugin({
|
|
disable: !env.optimizeImages,
|
|
externalImages: {
|
|
context: path.resolve(__dirname, 'src/ui/images'),
|
|
sources: glob.sync('src/ui/images/settings/*.png'),
|
|
destination: path.resolve(__dirname, 'images')
|
|
},
|
|
cacheFolder: path.resolve(__dirname, '.cache-images'),
|
|
gifsicle: null,
|
|
jpegtran: null,
|
|
optipng: null,
|
|
pngquant: {
|
|
quality: '85-100',
|
|
speed: env.production ? 1 : 10
|
|
},
|
|
svgo: null
|
|
})
|
|
];
|
|
|
|
return {
|
|
name: 'ui',
|
|
context: path.resolve(__dirname, 'src/ui'),
|
|
// This is ugly having main.scss on both bundles, but if it is added separately it will generate a js bundle :(
|
|
entry: {
|
|
settings: ['./settings/index.ts', './scss/main.scss'],
|
|
welcome: ['./welcome/index.ts', './scss/main.scss']
|
|
// main: ['./scss/main.scss']
|
|
},
|
|
mode: env.production ? 'production' : 'development',
|
|
devtool: env.production ? undefined : 'eval-source-map',
|
|
output: {
|
|
filename: '[name].js',
|
|
path: path.resolve(__dirname, 'dist/ui'),
|
|
publicPath: '{{root}}/dist/ui/'
|
|
},
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: /\.ts$/,
|
|
enforce: 'pre',
|
|
use: [
|
|
{
|
|
loader: 'tslint-loader',
|
|
options: {
|
|
tsConfigFile: 'ui.tsconfig.json'
|
|
}
|
|
}
|
|
],
|
|
exclude: /node_modules/
|
|
},
|
|
{
|
|
test: /\.tsx?$/,
|
|
use: {
|
|
loader: 'ts-loader',
|
|
options: {
|
|
configFile: 'ui.tsconfig.json'
|
|
}
|
|
},
|
|
exclude: /node_modules|\.d\.ts$/
|
|
},
|
|
{
|
|
test: /\.scss$/,
|
|
use: [
|
|
{
|
|
loader: MiniCssExtractPlugin.loader
|
|
},
|
|
{
|
|
loader: 'css-loader',
|
|
options: {
|
|
sourceMap: true,
|
|
url: false
|
|
}
|
|
},
|
|
{
|
|
loader: 'sass-loader',
|
|
options: {
|
|
sourceMap: true
|
|
}
|
|
}
|
|
],
|
|
exclude: /node_modules/
|
|
}
|
|
]
|
|
},
|
|
resolve: {
|
|
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
|
|
modules: [path.resolve(__dirname, 'src/ui'), 'node_modules']
|
|
},
|
|
plugins: plugins,
|
|
stats: {
|
|
all: false,
|
|
assets: true,
|
|
builtAt: true,
|
|
env: true,
|
|
errors: true,
|
|
timings: true,
|
|
warnings: true
|
|
}
|
|
};
|
|
}
|