using my boilerplate yuh
This commit is contained in:
116
webpack/plugins/buildProcessPlugins.ts
Normal file
116
webpack/plugins/buildProcessPlugins.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import path from 'path';
|
||||
import dotenv from 'dotenv';
|
||||
import webpack, { WebpackPluginInstance } from 'webpack';
|
||||
import { EntryId } from 'webpack/webpack.config';
|
||||
import CreateFileWebpack from 'create-file-webpack';
|
||||
import CopyWebpackPlugin from 'copy-webpack-plugin';
|
||||
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
|
||||
import WebpackBuildNotifierPlugin from 'webpack-build-notifier';
|
||||
import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
|
||||
import HTMLWebpackPlugin from 'html-webpack-plugin';
|
||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||
import TypeErrorNotifierPlugin from './custom/TypeErrorNotifierPlugin';
|
||||
|
||||
/**
|
||||
* Gets the plugins that are used in the build process
|
||||
* @param mode the environment that the build is running in
|
||||
* @param htmlEntries the entry points that need an html file
|
||||
* @param manifest the manifest.json file
|
||||
* @returns an array of webpack plugins
|
||||
*/
|
||||
export function getBuildPlugins(mode: Environment, htmlEntries: EntryId[], manifest: chrome.runtime.ManifestV3) {
|
||||
let plugins: WebpackPluginInstance[] = [];
|
||||
|
||||
// show the progress of the build
|
||||
plugins.push(new webpack.ProgressPlugin());
|
||||
|
||||
// make sure that the paths are case sensitive
|
||||
plugins.push(new CaseSensitivePathsPlugin());
|
||||
|
||||
// specify how the outputed css files should be named
|
||||
plugins.push(
|
||||
new MiniCssExtractPlugin({
|
||||
filename: 'static/css/[name].css',
|
||||
chunkFilename: 'static/css/[name].chunk.css',
|
||||
})
|
||||
);
|
||||
|
||||
// create an html file for each entry point that needs one
|
||||
for (const entryId of htmlEntries) {
|
||||
// if (!entries[entryId]) return;
|
||||
plugins.push(
|
||||
new HTMLWebpackPlugin({
|
||||
hash: false,
|
||||
filename: `${entryId}.html`,
|
||||
chunks: [entryId],
|
||||
title: `${manifest.short_name} ${entryId} `,
|
||||
template: path.resolve('webpack', 'plugins', 'template.html'),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// write the manifest.json file to the build directory
|
||||
plugins.push(
|
||||
new CreateFileWebpack({
|
||||
path: path.resolve('build'),
|
||||
fileName: 'manifest.json',
|
||||
content: JSON.stringify(manifest, null, 2),
|
||||
})
|
||||
);
|
||||
|
||||
// copy the public directory to the build directory, but only copy the icons for the current mode
|
||||
plugins.push(
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: path.resolve('public'),
|
||||
filter: path => (path.includes('icons') ? path.includes(mode) : true),
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
// run the typescript checker in a separate process
|
||||
plugins.push(
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
async: false,
|
||||
})
|
||||
);
|
||||
|
||||
// notify the developer of build events when in development mode
|
||||
if (mode === 'development') {
|
||||
plugins.push(
|
||||
new WebpackBuildNotifierPlugin({
|
||||
title: `${manifest.short_name} v${manifest.version} ${mode}`,
|
||||
logo: path.resolve('public', 'icons', 'icon_production_128.png'),
|
||||
failureSound: 'Ping',
|
||||
showDuration: true,
|
||||
suppressWarning: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// notify the developer of type errors
|
||||
plugins.push(new TypeErrorNotifierPlugin());
|
||||
|
||||
// define the environment variables that are available within the extension code
|
||||
plugins.push(
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': JSON.stringify({
|
||||
SEMANTIC_VERSION: process.env.SEMANTIC_VERSION,
|
||||
NODE_ENV: mode,
|
||||
...dotenv.config({ path: `.env.${mode}` }).parsed,
|
||||
} satisfies typeof process.env),
|
||||
})
|
||||
);
|
||||
|
||||
// provide some global nodejs variables so that nodejs libraries can be used
|
||||
plugins.push(
|
||||
new webpack.ProvidePlugin({
|
||||
Buffer: ['buffer', 'Buffer'],
|
||||
process: 'process/browser',
|
||||
})
|
||||
);
|
||||
|
||||
return plugins;
|
||||
}
|
||||
84
webpack/plugins/custom/TypeErrorNotifierPlugin.ts
Normal file
84
webpack/plugins/custom/TypeErrorNotifierPlugin.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { Compiler } from 'webpack';
|
||||
import path from 'path';
|
||||
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
|
||||
import WebpackBuildNotifierPlugin from 'webpack-build-notifier';
|
||||
import { Issue, IssueLocation } from 'fork-ts-checker-webpack-plugin/lib/issue';
|
||||
|
||||
interface Resource {
|
||||
path: string;
|
||||
location: IssueLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* This plugin hooks into the fork-ts-checker-webpack-plugin and
|
||||
* notifies the developer of type errors using the webpack-build-notifier plugin.
|
||||
*/
|
||||
export default class TypeErrorNotifierPlugin {
|
||||
apply(compiler: Compiler) {
|
||||
// hook into the fork-ts-checker-webpack-plugin
|
||||
const hooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(compiler);
|
||||
hooks.issues.tap('MyPlugin', issues => {
|
||||
const errors = issues.filter(issue => issue.severity === 'error');
|
||||
if (!errors?.[0]?.message) {
|
||||
return errors;
|
||||
}
|
||||
|
||||
let error = errors[0];
|
||||
let resource = getErrorResource(error);
|
||||
|
||||
try {
|
||||
notifyTypeError(resource, error.message, errors);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
return errors;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function notifyTypeError(resource: Resource, message: string, errors: Issue[]) {
|
||||
const { line, column } = resource.location.start;
|
||||
|
||||
const buildNotifier = new WebpackBuildNotifierPlugin({
|
||||
logo: path.resolve('public', 'icons', 'icon_production_128.png'),
|
||||
compilationSound: 'Pop',
|
||||
failureSound: 'Sosumi',
|
||||
title: `TS: ${errors.length} errors`,
|
||||
notifyOptions: {
|
||||
open: `vscode://file/${resource.path}:${line}:${column}`,
|
||||
},
|
||||
});
|
||||
|
||||
const fakeInput = {
|
||||
hasErrors: () => true,
|
||||
compilation: {
|
||||
children: null,
|
||||
errors: [
|
||||
{
|
||||
message,
|
||||
module: {
|
||||
resource: resource.path,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
// @ts-ignore - private method
|
||||
buildNotifier.onCompilationDone(fakeInput);
|
||||
}
|
||||
|
||||
function getErrorResource(error: Issue): Resource {
|
||||
return {
|
||||
path: error.file ?? '',
|
||||
location: error.location ?? {
|
||||
end: {
|
||||
column: 0,
|
||||
line: 0,
|
||||
},
|
||||
start: {
|
||||
column: 0,
|
||||
line: 0,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
36
webpack/plugins/custom/hotReloadServer.ts
Normal file
36
webpack/plugins/custom/hotReloadServer.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Server } from 'socket.io';
|
||||
import { Compiler } from 'webpack';
|
||||
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
|
||||
|
||||
// Name of the plugin
|
||||
const PLUGIN_NAME = 'HotReloadServer';
|
||||
|
||||
// How long to wait before reloading the browser after a successful build
|
||||
const RELOAD_LOCKOUT = 2000;
|
||||
|
||||
// we want to cache all the "reload requests" here so we don't have to keep re-compiling the app while typing
|
||||
const reloads: NodeJS.Timeout[] = [];
|
||||
|
||||
let io: Server;
|
||||
|
||||
export function initializeHotReloading(port: number, compiler: Compiler) {
|
||||
io = new Server(port);
|
||||
|
||||
const hooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(compiler);
|
||||
hooks.issues.tap(PLUGIN_NAME, (issues, compilation) => {
|
||||
const typeErrors = issues.filter(issue => issue.severity === 'error');
|
||||
const buildErrors = compilation?.errors ?? [];
|
||||
// if no errors (thus successful build), lets queue up a reload for the browser
|
||||
if (typeErrors.length === 0 && buildErrors.length === 0) {
|
||||
reloads.push(setTimeout(() => io.emit('reload'), RELOAD_LOCKOUT));
|
||||
}
|
||||
return typeErrors;
|
||||
});
|
||||
|
||||
// if a recompile is triggered, we want to clear out all the queue'd reloads
|
||||
// (so we don't spam-reload the extension while we are still typing
|
||||
compiler.hooks.compile.tap(PLUGIN_NAME, () => {
|
||||
reloads.forEach(reload => clearTimeout(reload));
|
||||
reloads.length = 0;
|
||||
});
|
||||
}
|
||||
12
webpack/plugins/moduleResolutionPlugins.ts
Normal file
12
webpack/plugins/moduleResolutionPlugins.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
|
||||
import path from 'path';
|
||||
import ModuleScopePlugin from 'react-dev-utils/ModuleScopePlugin';
|
||||
|
||||
export const moduleResolutionPlugins = [
|
||||
// this will make sure that webpack uses the tsconfig path aliases
|
||||
new TsconfigPathsPlugin({
|
||||
configFile: path.resolve('src', 'tsconfig.json'),
|
||||
}),
|
||||
// this will make sure that we don't import anything outside of the src directory from the src directory
|
||||
new ModuleScopePlugin(path.resolve('src'), path.resolve('package.json')),
|
||||
];
|
||||
32
webpack/plugins/template.html
Normal file
32
webpack/plugins/template.html
Normal file
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
--></body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user