1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-27 12:55:55 +00:00
FrankerFaceZ/webpack.config.js

393 lines
8 KiB
JavaScript
Raw Permalink Normal View History

/* global module __dirname */
const path = require('path');
const semver = require('semver');
const {exec, execSync} = require('child_process');
const { CycloneDxWebpackPlugin } = require('@cyclonedx/webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const { EsbuildPlugin } = require('esbuild-loader');
const CopyPlugin = require('copy-webpack-plugin');
if ( process.env.NODE_ENV == null )
process.env.NODE_ENV = 'production';
// Are we in development?
const DEV_SERVER = process.env.WEBPACK_SERVE == 'true';
const DEV_BUILD = process.env.NODE_ENV !== 'production';
// Is this for an extension?
const FOR_EXTENSION = !! process.env.FFZ_EXTENSION;
// Get the public path.
const FILE_PATH = DEV_SERVER
? 'https://localhost:8000/script/'
: FOR_EXTENSION
? ''
: 'https://cdn2.frankerfacez.com/static/';
console.log('NODE_ENV:', process.env.NODE_ENV);
console.log('FOR_EXTENSION:', FOR_EXTENSION, FOR_EXTENSION ? ` (${process.env.FFZ_EXTENSION})` : '');
console.log('IS_DEV_BUILD:', DEV_BUILD);
console.log('IS SERVE:', DEV_SERVER);
console.log('FILE PATH:', FILE_PATH);
// Version Stuff
const VERSION = semver.parse(require('./package.json').version);
const commit_hash = DEV_SERVER
? null
: process.env.CLIENT_COMMIT?.length > 0
? process.env.CLIENT_COMMIT
: execSync('git rev-parse HEAD').toString().trim();
// The Config
const ENTRY_POINTS = {
bridge: './src/bridge.js',
esbridge: './src/esbridge.js',
player: './src/player.js',
avalon: './src/main.ts',
clips: './src/clips.js'
};
if ( FOR_EXTENSION )
ENTRY_POINTS.worker = './src/worker.ts';
const COPY_PATTERNS = [
{
from: FOR_EXTENSION
? './src/entry_ext.js'
: './src/entry.js',
to: (DEV_SERVER || DEV_BUILD)
? 'script.js'
: 'script.min.js'
},
];
const TARGET = 'es2020';
/** @type {import('webpack').Configuration} */
const config = {
mode: DEV_BUILD
? 'development'
: 'production',
devtool: DEV_BUILD
? 'inline-source-map'
: 'source-map',
target: ['web', TARGET],
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
alias: {
res: path.resolve(__dirname, 'res/'),
styles: path.resolve(__dirname, 'styles/'),
root: __dirname,
src: path.resolve(__dirname, 'src/'),
utilities: path.resolve(__dirname, 'src/utilities/'),
site: path.resolve(__dirname, 'src/sites/twitch-twilight/')
}
},
node: {
global: false
},
entry: ENTRY_POINTS,
externals: [
({context, request}, callback) => {
if ( request === 'vue' && ! /utilities/.test(context) )
return callback(null, 'root ffzVue');
callback();
}
],
output: {
chunkFormat: 'array-push',
clean: true,
publicPath: FOR_EXTENSION
? 'auto'
: FILE_PATH,
path: path.resolve(__dirname, 'dist'),
filename: (FOR_EXTENSION || DEV_SERVER)
? '[name].js'
: '[name].[contenthash:8].js',
chunkLoadingGlobal: 'ffzWebpackJsonp',
crossOriginLoading: 'anonymous'
},
optimization: {
minimizer: [
new EsbuildPlugin({
target: TARGET,
keepNames: true
})
],
splitChunks: {
chunks(chunk) {
return ! Object.keys(ENTRY_POINTS).includes(chunk.name);
},
cacheGroups: {
vendors: false
}
}
},
performance: {
hints: false,
},
plugins: [
new CycloneDxWebpackPlugin({
specVersion: '1.6',
outputLocation: './bom',
includeWellknown: false
}),
new CopyPlugin({
patterns: COPY_PATTERNS
}),
new VueLoaderPlugin(),
new EsbuildPlugin({
define: {
__version_major__: JSON.stringify(VERSION.major),
__version_minor__: JSON.stringify(VERSION.minor),
__version_patch__: JSON.stringify(VERSION.patch),
__version_prerelease__: JSON.stringify(VERSION.prerelease),
__version_build__: JSON.stringify(process.env.FFZ_BUILD || null),
__git_commit__: JSON.stringify(commit_hash),
__extension__: FOR_EXTENSION
? JSON.stringify(process.env.FFZ_EXTENSION)
: JSON.stringify(false)
}
}),
new WebpackManifestPlugin({
publicPath: ''
})
],
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'esbuild-loader',
options: {
loader: 'jsx',
jsxFactory: 'createElement',
target: TARGET
}
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
loader: 'esbuild-loader',
options: {
loader: 'tsx',
jsxFactory: 'createElement',
target: TARGET
}
},
{
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
use: [
'graphql-tag/loader',
'minify-graphql-loader'
]
},
{
test: /\.json$/,
include: /src/,
type: 'asset/resource',
generator: {
filename: (FOR_EXTENSION || DEV_BUILD)
? '[name].json'
: '[name].[contenthash:8].json'
}
},
{
// This stupid rule goes out to Mozilla, who consistantly
// manage to have this one file not included in the bundle
// the same way as every other build on every other machine
// out of like twelve I've tested. So fine. We'll do it
// your way. Whatever. I don't care.
test: /entities.json$/,
include: /node_modules/,
type: 'asset/resource',
generator: {
filename: (FOR_EXTENSION || DEV_BUILD)
? '[name].json'
: '[name].[contenthash:8].json'
}
},
{
test: /\.(?:otf|eot|ttf|woff|woff2)$/,
use: [{
loader: 'file-loader',
options: {
name: (FOR_EXTENSION || DEV_BUILD)
? '[name].[ext]'
: '[name].[contenthash:8].[ext]'
}
}]
},
{
test: /\.md$/,
type: 'asset/source',
},
{
test: /\.svg$/,
type: 'asset/source'
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.(?:sa|sc|c)ss$/,
resourceQuery: {
not: [
/css_tweaks/
]
},
use: [
{
loader: 'file-loader',
options: {
name: (FOR_EXTENSION || DEV_BUILD)
? '[name].css'
: '[name].[contenthash:8].css'
}
},
{
loader: 'extract-loader',
options: {
publicPath: ''
}
},
{
loader: 'css-loader',
options: {
esModule: false,
sourceMap: DEV_BUILD ? true : false
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
},
{
test: /\.(?:sa|sc|c)ss$/,
resourceQuery: /css_tweaks/,
use: [
{
loader: 'raw-loader'
},
{
loader: 'extract-loader'
},
{
loader: 'css-loader',
options: {
esModule: false,
sourceMap: DEV_BUILD ? true : false
}
},
{
loader: 'sass-loader',
options: {
sourceMap: false
}
}
]
}
]
}
};
if ( DEV_SERVER )
config.devServer = {
client: false,
webSocketServer: false,
liveReload: false,
hot: false,
server: 'https',
port: 8000,
compress: true,
allowedHosts: [
'.twitch.tv',
'.frankerfacez.com'
],
static: {
directory: path.join(__dirname, 'dev_cdn'),
},
devMiddleware: {
publicPath: '/script/',
},
proxy: [
{
context: ['**'],
target: 'https://cdn2.frankerfacez.com/',
changeOrigin: true
},
],
setupMiddlewares: (middlewares, devServer) => {
devServer.app.get('/update_font', (req, res) => {
const proc = exec('npm run font:save');
proc.stdout.on('data', data => {
console.log('FONT>>', data);
});
proc.stderr.on('data', data => {
console.error('FONT>>', data);
});
proc.on('close', code => {
console.log('FONT>> Exited with code', code);
res.redirect(req.headers.referer);
});
});
devServer.app.get('/dev_server', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Private-Network', 'true');
res.json({
path: process.cwd(),
version: 2
})
});
middlewares.unshift((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Private-Network', 'true');
next();
});
return middlewares.filter(middleware => middleware.name !== 'cross-origin-header-check');
}
};
module.exports = config;