Files
chatGPTBox/build.mjs
T
AceLam d24958f9a0 Add ChatGLM API (#567)
* Add ChatGLM API

* add minimal build

* a small patch

---------

Co-authored-by: josc146 <josStorer@outlook.com>
2023-12-03 23:31:04 +08:00

364 lines
9.5 KiB
JavaScript

import archiver from 'archiver'
import fs from 'fs-extra'
import path from 'path'
import webpack from 'webpack'
import ProgressBarPlugin from 'progress-bar-webpack-plugin'
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
import TerserPlugin from 'terser-webpack-plugin'
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
const outdir = 'build'
const __dirname = path.resolve()
const isProduction = process.argv[2] !== '--development' // --production and --analyze are both production
const isAnalyzing = process.argv[2] === '--analyze'
async function deleteOldDir() {
await fs.rm(outdir, { recursive: true, force: true })
}
async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, callback) {
const shared = [
'preact',
'webextension-polyfill',
'@primer/octicons-react',
'react-bootstrap-icons',
'countries-list',
'i18next',
'react-i18next',
'react-tabs',
'./src/utils',
'./src/_locales/i18n-react',
]
if (isWithoutKatex) shared.push('./src/components')
const compiler = webpack({
entry: {
'content-script': {
import: './src/content-script/index.jsx',
dependOn: 'shared',
},
background: {
import: './src/background/index.mjs',
},
popup: {
import: './src/popup/index.jsx',
dependOn: 'shared',
},
IndependentPanel: {
import: './src/pages/IndependentPanel/index.jsx',
dependOn: 'shared',
},
shared: shared,
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, outdir),
},
mode: isProduction ? 'production' : 'development',
devtool: isProduction ? false : 'inline-source-map',
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
output: { ascii_only: true },
},
}),
new CssMinimizerPlugin(),
],
concatenateModules: !isAnalyzing,
},
plugins: [
minimal
? undefined
: new webpack.ProvidePlugin({
process: 'process/browser.js',
Buffer: ['buffer', 'Buffer'],
}),
new ProgressBarPlugin({
format: ' build [:bar] :percent (:elapsed seconds)',
clear: false,
}),
new MiniCssExtractPlugin({
filename: '[name].css',
}),
new BundleAnalyzerPlugin({
analyzerMode: isAnalyzing ? 'static' : 'disable',
}),
...(isWithoutKatex
? [
new webpack.NormalModuleReplacementPlugin(/markdown\.jsx/, (result) => {
if (result.request) {
result.request = result.request.replace(
'markdown.jsx',
'markdown-without-katex.jsx',
)
}
}),
]
: []),
],
resolve: {
extensions: ['.jsx', '.mjs', '.js'],
alias: {
parse5: path.resolve(__dirname, 'node_modules/parse5'),
...(minimal
? {}
: {
util: path.resolve(__dirname, 'node_modules/util'),
buffer: path.resolve(__dirname, 'node_modules/buffer'),
stream: 'stream-browserify',
crypto: 'crypto-browserify',
}),
},
},
module: {
rules: [
{
test: /\.m?jsx?$/,
exclude: /(node_modules)/,
resolve: {
fullySpecified: false,
},
use: [
{
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
{
plugins: ['@babel/plugin-transform-runtime'],
},
],
plugins: [
[
'@babel/plugin-transform-react-jsx',
{
runtime: 'automatic',
importSource: 'preact',
},
],
],
},
},
],
},
{
test: /\.s[ac]ss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
{
loader: 'sass-loader',
},
],
},
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
{
loader: 'less-loader',
},
],
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
},
],
},
{
test: /\.(woff|ttf)$/,
type: 'asset/resource',
generator: {
emit: false,
},
},
{
test: /\.woff2$/,
type: 'asset/inline',
},
{
test: /\.(jpg|png|svg)$/,
type: 'asset/inline',
},
{
test: /\.(graphql|gql)$/,
loader: 'graphql-tag/loader',
},
isWithoutTiktoken
? {
test: /crop-text\.mjs$/,
loader: 'string-replace-loader',
options: {
multiple: [
{
search: "import { encode } from '@nem035/gpt-3-encoder'",
replace: '',
},
{
search: 'encode(',
replace: 'String(',
},
],
},
}
: {},
minimal
? {
test: /styles\.scss$/,
loader: 'string-replace-loader',
options: {
multiple: [
{
search: "@import '../fonts/styles.css';",
replace: '',
},
],
},
}
: {},
minimal
? {
test: /index\.mjs$/,
loader: 'string-replace-loader',
options: {
multiple: [
{
search: 'import { generateAnswersWithChatGLMApi }',
replace: '//',
},
{
search: 'await generateAnswersWithChatGLMApi',
replace: '//',
},
{
search: 'chatglmTurbo',
replace: '//',
},
{
search: "'chatglmTurbo",
replace: '//',
},
],
},
}
: {},
],
},
})
if (isProduction) compiler.run(callback)
else compiler.watch({}, callback)
}
async function zipFolder(dir) {
const output = fs.createWriteStream(`${dir}.zip`)
const archive = archiver('zip', {
zlib: { level: 9 },
})
archive.pipe(output)
archive.directory(dir, false)
await archive.finalize()
}
async function copyFiles(entryPoints, targetDir) {
if (!fs.existsSync(targetDir)) await fs.mkdir(targetDir)
await Promise.all(
entryPoints.map(async (entryPoint) => {
await fs.copy(entryPoint.src, `${targetDir}/${entryPoint.dst}`)
}),
)
}
async function finishOutput(outputDirSuffix) {
const commonFiles = [
{ src: 'src/logo.png', dst: 'logo.png' },
{ src: 'src/rules.json', dst: 'rules.json' },
{ src: 'build/shared.js', dst: 'shared.js' },
{ src: 'build/content-script.css', dst: 'content-script.css' }, // shared
{ src: 'build/content-script.js', dst: 'content-script.js' },
{ src: 'build/background.js', dst: 'background.js' },
{ src: 'build/popup.js', dst: 'popup.js' },
{ src: 'build/popup.css', dst: 'popup.css' },
{ src: 'src/popup/index.html', dst: 'popup.html' },
{ src: 'build/IndependentPanel.js', dst: 'IndependentPanel.js' },
{ src: 'src/pages/IndependentPanel/index.html', dst: 'IndependentPanel.html' },
]
// chromium
const chromiumOutputDir = `./${outdir}/chromium${outputDirSuffix}`
await copyFiles(
[...commonFiles, { src: 'src/manifest.json', dst: 'manifest.json' }],
chromiumOutputDir,
)
if (isProduction) await zipFolder(chromiumOutputDir)
// firefox
const firefoxOutputDir = `./${outdir}/firefox${outputDirSuffix}`
await copyFiles(
[...commonFiles, { src: 'src/manifest.v2.json', dst: 'manifest.json' }],
firefoxOutputDir,
)
if (isProduction) await zipFolder(firefoxOutputDir)
}
function generateWebpackCallback(finishOutputFunc) {
return async function webpackCallback(err, stats) {
if (err || stats.hasErrors()) {
console.error(err || stats.toString())
return
}
// console.log(stats.toString())
await finishOutputFunc()
}
}
async function build() {
await deleteOldDir()
if (isProduction && !isAnalyzing) {
// await runWebpack(
// true,
// false,
// generateWebpackCallback(() => finishOutput('-without-katex')),
// )
// await new Promise((r) => setTimeout(r, 5000))
await runWebpack(
true,
true,
true,
generateWebpackCallback(() => finishOutput('-without-katex-and-tiktoken')),
)
await new Promise((r) => setTimeout(r, 10000))
}
await runWebpack(
false,
false,
false,
generateWebpackCallback(() => finishOutput('')),
)
}
build()