dsifford/academic-bloggers-toolkit

View on GitHub
webpack.config.ts

Summary

Maintainability
A
2 hrs
Test Coverage
File `webpack.config.ts` has 253 lines of code (exceeds 250 allowed). Consider refactoring.
/* eslint-disable @typescript-eslint/no-var-requires */
import { promises as fs } from 'fs';
import path from 'path';
import { promisify } from 'util';
 
import DependencyExtractionPlugin from '@wordpress/dependency-extraction-webpack-plugin';
import { CheckerPlugin, TsConfigPathsPlugin } from 'awesome-typescript-loader';
import BrowserSyncPlugin from 'browser-sync-webpack-plugin';
import CopyWebpackPlugin from 'copy-webpack-plugin';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import rimrafLib from 'rimraf';
import { rollup } from 'rollup';
import commonjs from 'rollup-plugin-commonjs';
import resolve from 'rollup-plugin-node-resolve';
import { terser } from 'rollup-plugin-terser';
import { Configuration, Plugin, ProgressPlugin } from 'webpack';
 
import { version as VERSION } from './package.json';
 
const rimraf = promisify(rimrafLib);
 
// eslint-disable-next-line
export default async (_: any, argv: any): Promise<Configuration> => {
const IS_PRODUCTION = argv.mode === 'production';
const CHANGELOG = await getMostRecentChangelogEntry();
 
// Clean out dist directory
await rimraf(path.join(__dirname, 'dist', '*'));
 
await Promise.all([
rollup({
input: 'citeproc',
plugins: IS_PRODUCTION
? [resolve(), commonjs(), terser()]
: [resolve(), commonjs()],
}),
]).then(async ([citeproc]) =>
Promise.all([
citeproc.write({
file: 'dist/vendor/citeproc.js',
format: 'iife',
name: 'CSL',
}),
]),
);
 
const plugins = new Set<Plugin>([
new DependencyExtractionPlugin({
injectPolyfill: true,
requestToExternal(request) {
if (request === 'citeproc') {
return 'CSL';
}
return;
},
}),
new MiniCssExtractPlugin(),
new CopyWebpackPlugin([
{
from: '**/*.{php,mo,pot}',
ignore: ['academic-bloggers-toolkit.php'],
},
{
from: '*.json',
transform(content) {
return JSON.stringify(JSON.parse(content.toString()));
},
},
{
from: path.resolve(__dirname, 'LICENSE'),
},
{
from: 'academic-bloggers-toolkit.php',
transform(content) {
return content.toString().replace(/{{VERSION}}/g, VERSION);
},
},
{
from: 'readme.txt',
transform(content) {
return content
.toString()
.replace(/{{VERSION}}/g, VERSION)
.replace(/{{CHANGELOG}}/g, CHANGELOG);
},
},
]),
new CheckerPlugin(),
]);
 
if (IS_PRODUCTION) {
plugins.add(new ProgressPlugin());
} else {
plugins.add(
new BrowserSyncPlugin({
proxy: 'localhost:8080',
open: false,
reloadDebounce: 2000,
port: 3005,
notify: false,
}),
);
}
 
const TS_BASE_CONFIG = {
silent: argv.json,
useCache: !IS_PRODUCTION,
cacheDirectory: path.resolve(
__dirname,
'node_modules/.cache/awesome-typescript-loader',
),
reportFiles: ['**/*.{ts,tsx}', '!**/__tests__/**'],
};
 
return {
devtool: IS_PRODUCTION ? 'source-map' : 'cheap-module-eval-source-map',
watchOptions: {
ignored: /(node_modules|__tests__)/,
},
context: path.resolve(__dirname, 'src'),
entry: {
'bundle/editor': 'js/gutenberg',
'bundle/editor-blocks': 'js/gutenberg/blocks',
'bundle/editor-formats': 'js/gutenberg/formats',
'bundle/editor-stores': 'js/stores',
'bundle/frontend': 'js/frontend',
'bundle/options-page': 'js/options-page',
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist'),
},
resolve: {
alias: {
css: path.resolve(__dirname, 'src/css'),
},
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
extensions: ['*', '.ts', '.tsx', '.js', '.scss'],
plugins: [new TsConfigPathsPlugin()],
},
plugins: [...plugins],
stats: IS_PRODUCTION ? 'errors-warnings' : 'minimal',
module: {
rules: [
{
test: /\.tsx?$/,
sideEffects: false,
rules: [
{
loader: 'babel-loader',
},
{
oneOf: [
{
include: path.resolve(
__dirname,
'src/js/_legacy/workers',
),
use: [
{
loader: 'awesome-typescript-loader',
options: {
...TS_BASE_CONFIG,
configFileName: path.resolve(
__dirname,
'src/js/_legacy/workers/tsconfig.json',
),
instance: 'workers',
},
},
],
},
{
use: [
{
loader: 'awesome-typescript-loader',
options: {
...TS_BASE_CONFIG,
},
},
],
},
],
},
],
},
{
test: /\.scss$/,
rules: [
{
use: [MiniCssExtractPlugin.loader],
},
{
oneOf: [
{
resourceQuery: /global/,
use: [
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: false,
},
},
],
},
{
use: [
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: {
localIdentName:
'[name]__[local]___[hash:base64:5]',
},
localsConvention:
'camelCaseOnly',
},
},
],
},
],
},
{
use: [
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: [
require('postcss-preset-env')(),
...(IS_PRODUCTION
? [require('cssnano')()]
: []),
],
},
},
{
loader: 'sass-loader',
options: {
sassOptions: {
includePaths: ['src/css'],
},
},
},
],
},
],
},
],
},
};
};
 
function getMostRecentChangelogEntry(): Promise<string> {
return fs
.readFile(path.join(__dirname, 'CHANGELOG.md'), { encoding: 'utf-8' })
.then(contents => {
const entry = /(^## .*?)\n^## /ms.exec(contents);
if (!entry || !entry[1]) {
throw new Error('Error parsing last changelog entry');
}
return entry[1];
})
.then(entry =>
entry.replace(/^## (\S+)/, '= $1 =').replace(/^-/gm, '*'),
);
}