web-extension-starter/webpack.config.js
2023-08-27 07:18:11 -07:00

202 lines
6.7 KiB
JavaScript

const path = require("path");
const webpack = require("webpack");
const FilemanagerPlugin = require("filemanager-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const ExtensionReloader = require("webpack-extension-reloader");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const WextManifestWebpackPlugin = require("wext-manifest-webpack-plugin");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const viewsPath = path.join(__dirname, "views");
const sourcePath = path.join(__dirname, "source");
const destPath = path.join(__dirname, "extension");
const nodeEnv = process.env.NODE_ENV || "development";
const targetBrowser = process.env.TARGET_BROWSER;
const extensionReloaderPlugin =
nodeEnv === "development"
? new ExtensionReloader({
port: 9090,
reloadPage: true,
entries: {
// TODO: reload manifest on update
contentScript: "contentScript",
extensionPage: ["popup", "options"],
},
})
: () => {
this.apply = () => {};
};
const getExtensionFileType = (browser) => {
if (browser === "opera") {
return "crx";
}
if (browser === "firefox") {
return "xpi";
}
return "zip";
};
module.exports = {
devtool: false, // https://github.com/webpack/webpack/issues/1194#issuecomment-560382342
stats: {
all: false,
builtAt: true,
errors: true,
hash: true,
},
mode: nodeEnv,
entry: {
manifest: path.join(sourcePath, "manifest.json"),
contentScript: path.join(sourcePath, "ContentScript", "index.ts"),
},
output: {
path: path.join(destPath, targetBrowser),
filename: "js/[name].bundle.js",
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".json"],
alias: {
"webextension-polyfill-ts": path.resolve(
path.join(__dirname, "node_modules", "webextension-polyfill-ts")
),
},
},
module: {
rules: [
{
type: "javascript/auto", // prevent webpack handling json with its own loaders,
test: /manifest\.json$/,
use: {
loader: "wext-manifest-loader",
options: {
usePackageJSONVersion: true, // set to false to not use package.json version for manifest
},
},
exclude: /node_modules/,
},
{
test: /\.(js|ts)x?$/,
loader: "babel-loader",
exclude: /node_modules/,
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader, // It creates a CSS file per JS file which contains CSS
},
{
loader: "css-loader", // Takes the CSS files and returns the CSS with imports and url(...) for Webpack
options: {
sourceMap: true,
},
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"autoprefixer",
{
// Options
},
],
],
},
},
},
"resolve-url-loader", // Rewrites relative paths in url() statements
"sass-loader", // Takes the Sass/SCSS file and compiles to the CSS
],
},
],
},
plugins: [
// Plugin to not generate js bundle for manifest entry
new WextManifestWebpackPlugin(),
// Generate sourcemaps
new webpack.SourceMapDevToolPlugin({ filename: false }),
new ForkTsCheckerWebpackPlugin(),
// environmental variables
new webpack.EnvironmentPlugin(["NODE_ENV", "TARGET_BROWSER"]),
// delete previous build files
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: [
path.join(process.cwd(), `extension/${targetBrowser}`),
path.join(
process.cwd(),
`extension/${targetBrowser}.${getExtensionFileType(
targetBrowser
)}`
),
],
cleanStaleWebpackAssets: false,
verbose: true,
}),
// write css file(s) to build folder
new MiniCssExtractPlugin({ filename: "css/[name].css" }),
// copy static assets
new CopyWebpackPlugin({
patterns: [{ from: "source/assets", to: "assets" }],
}),
// plugin to enable browser reloading in development mode
extensionReloaderPlugin,
],
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
terserOptions: {
format: {
comments: false,
},
},
extractComments: false,
}),
new OptimizeCSSAssetsPlugin({
cssProcessorPluginOptions: {
preset: [
"default",
{ discardComments: { removeAll: true } },
],
},
}),
new FilemanagerPlugin({
events: {
onEnd: {
archive: [
{
format: "zip",
source: path.join(destPath, targetBrowser),
destination: `${path.join(
destPath,
targetBrowser
)}.${getExtensionFileType(targetBrowser)}`,
options: { zlib: { level: 6 } },
},
],
},
},
}),
],
},
};