354bed1c32
This commit also adds an error message for when the Content Security Policy is likely at fault for blocking it.
206 lines
6.0 KiB
TypeScript
206 lines
6.0 KiB
TypeScript
import path from 'path';
|
|
import pluginReplace from '@rollup/plugin-replace';
|
|
import pluginVue from '@vitejs/plugin-vue';
|
|
import { type UserConfig, defineConfig } from 'vite';
|
|
import { localesVersion } from '../../locales/version.js';
|
|
import locales from '../../locales/index.js';
|
|
import meta from '../../package.json';
|
|
import packageInfo from './package.json' with { type: 'json' };
|
|
import pluginUnwindCssModuleClassName from './lib/rollup-plugin-unwind-css-module-class-name.js';
|
|
import pluginJson5 from './vite.json5.js';
|
|
import { pluginReplaceIcons } from './vite.replaceIcons.js';
|
|
|
|
const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.json', '.json5', '.svg', '.sass', '.scss', '.css', '.vue', '.wasm'];
|
|
|
|
/**
|
|
* Misskeyのフロントエンドにバンドルせず、CDNなどから別途読み込むリソースを記述する。
|
|
* CDNを使わずにバンドルしたい場合、以下の配列から該当要素を削除orコメントアウトすればOK
|
|
*/
|
|
const externalPackages = [
|
|
// shiki(コードブロックのシンタックスハイライトで使用中)はテーマ・言語の定義の容量が大きいため、それらはCDNから読み込む
|
|
{
|
|
name: 'shiki',
|
|
match: /^shiki\/(?<subPkg>(langs|themes))$/,
|
|
path(id: string, pattern: RegExp): string {
|
|
const match = pattern.exec(id)?.groups;
|
|
return match
|
|
? `https://esm.sh/shiki@${packageInfo.dependencies.shiki}/${match['subPkg']}`
|
|
: id;
|
|
},
|
|
},
|
|
// sharkey: Used for SkFlashPlayer, has large wasm files so it's loaded via Ruffle's preferred CDN
|
|
{
|
|
name: 'ruffle',
|
|
match: /^@ruffle-rs\/ruffle\/?(?<file>.*)$/,
|
|
path(id: string, pattern: RegExp): string {
|
|
const match = pattern.exec(id)?.groups;
|
|
return match
|
|
? `https://esm.sh/@ruffle-rs/ruffle@${packageInfo.dependencies['@ruffle-rs/ruffle']}/${match['file']}?raw`
|
|
: id;
|
|
},
|
|
},
|
|
];
|
|
|
|
const hash = (str: string, seed = 0): number => {
|
|
let h1 = 0xdeadbeef ^ seed,
|
|
h2 = 0x41c6ce57 ^ seed;
|
|
for (let i = 0, ch; i < str.length; i++) {
|
|
ch = str.charCodeAt(i);
|
|
h1 = Math.imul(h1 ^ ch, 2654435761);
|
|
h2 = Math.imul(h2 ^ ch, 1597334677);
|
|
}
|
|
|
|
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
|
|
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
|
|
|
|
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
|
|
};
|
|
|
|
const BASE62_DIGITS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
|
|
function toBase62(n: number): string {
|
|
if (n === 0) {
|
|
return '0';
|
|
}
|
|
let result = '';
|
|
while (n > 0) {
|
|
result = BASE62_DIGITS[n % BASE62_DIGITS.length] + result;
|
|
n = Math.floor(n / BASE62_DIGITS.length);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
export function getConfig(): UserConfig {
|
|
return {
|
|
base: '/vite/',
|
|
|
|
server: {
|
|
port: 5173,
|
|
headers: { // なんか効かない
|
|
'X-Frame-Options': 'DENY',
|
|
},
|
|
},
|
|
|
|
plugins: [
|
|
pluginVue(),
|
|
pluginUnwindCssModuleClassName(),
|
|
pluginJson5(),
|
|
...pluginReplaceIcons(),
|
|
...process.env.NODE_ENV === 'production'
|
|
? [
|
|
pluginReplace({
|
|
preventAssignment: true,
|
|
values: {
|
|
'isChromatic()': JSON.stringify(false),
|
|
},
|
|
}),
|
|
]
|
|
: [],
|
|
],
|
|
|
|
resolve: {
|
|
extensions,
|
|
alias: {
|
|
'@/': __dirname + '/src/',
|
|
'@@/': __dirname + '/../frontend-shared/',
|
|
'/client-assets/': __dirname + '/assets/',
|
|
'/static-assets/': __dirname + '/../backend/assets/',
|
|
'/fluent-emojis/': __dirname + '/../../fluent-emojis/dist/',
|
|
'/tossface/': __dirname + '/../../tossface-emojis/dist/',
|
|
'/fluent-emoji/': __dirname + '/../../fluent-emojis/dist/',
|
|
},
|
|
},
|
|
|
|
css: {
|
|
modules: {
|
|
generateScopedName(name, filename, _css): string {
|
|
const id = (path.relative(__dirname, filename.split('?')[0]) + '-' + name).replace(/[\\\/\.\?&=]/g, '-').replace(/(src-|vue-)/g, '');
|
|
const shortId = id.replace(/^(components(-global)?|widgets|ui(-_common_)?)-/, '');
|
|
return shortId + '-' + toBase62(hash(id)).substring(0, 4);
|
|
},
|
|
},
|
|
},
|
|
|
|
define: {
|
|
_VERSION_: JSON.stringify(meta.version),
|
|
_LANGS_: JSON.stringify(Object.entries(locales).map(([k, v]) => [k, v._lang_])),
|
|
_LANGS_VERSION_: JSON.stringify(localesVersion),
|
|
_ENV_: JSON.stringify(process.env.NODE_ENV),
|
|
_DEV_: process.env.NODE_ENV !== 'production',
|
|
_PERF_PREFIX_: JSON.stringify('Misskey:'),
|
|
_DATA_TRANSFER_DRIVE_FILE_: JSON.stringify('mk_drive_file'),
|
|
_DATA_TRANSFER_DRIVE_FOLDER_: JSON.stringify('mk_drive_folder'),
|
|
_DATA_TRANSFER_DECK_COLUMN_: JSON.stringify('mk_deck_column'),
|
|
__VUE_OPTIONS_API__: true,
|
|
__VUE_PROD_DEVTOOLS__: false,
|
|
},
|
|
|
|
build: {
|
|
target: [
|
|
'chrome116',
|
|
'firefox116',
|
|
'safari16',
|
|
],
|
|
manifest: 'manifest.json',
|
|
rollupOptions: {
|
|
input: {
|
|
app: './src/_boot_.ts',
|
|
},
|
|
external: externalPackages.map(p => p.match),
|
|
output: {
|
|
manualChunks: {
|
|
vue: ['vue'],
|
|
photoswipe: ['photoswipe', 'photoswipe/lightbox', 'photoswipe/style.css'],
|
|
},
|
|
chunkFileNames: process.env.NODE_ENV === 'production' ? '[hash:8].js' : '[name]-[hash:8].js',
|
|
assetFileNames: process.env.NODE_ENV === 'production' ? '[hash:8][extname]' : '[name]-[hash:8][extname]',
|
|
paths(id) {
|
|
for (const p of externalPackages) {
|
|
if (p.match.test(id)) {
|
|
return p.path(id, p.match);
|
|
}
|
|
}
|
|
|
|
return id;
|
|
},
|
|
},
|
|
},
|
|
cssCodeSplit: true,
|
|
outDir: __dirname + '/../../built/_frontend_vite_',
|
|
assetsDir: '.',
|
|
emptyOutDir: false,
|
|
sourcemap: process.env.NODE_ENV === 'development',
|
|
reportCompressedSize: false,
|
|
|
|
// https://vitejs.dev/guide/dep-pre-bundling.html#monorepos-and-linked-dependencies
|
|
commonjsOptions: {
|
|
include: [/misskey-js/, /misskey-reversi/, /misskey-bubble-game/, /node_modules/],
|
|
},
|
|
},
|
|
|
|
worker: {
|
|
format: 'es',
|
|
},
|
|
|
|
test: {
|
|
environment: 'happy-dom',
|
|
deps: {
|
|
optimizer: {
|
|
web: {
|
|
include: [
|
|
// XXX: misskey-dev/browser-image-resizer has no "type": "module"
|
|
'browser-image-resizer',
|
|
],
|
|
},
|
|
},
|
|
},
|
|
includeSource: ['src/**/*.ts'],
|
|
},
|
|
};
|
|
}
|
|
|
|
const config = defineConfig(({ command, mode }) => getConfig());
|
|
|
|
export default config;
|