Skip to content

Commit

Permalink
feat: add html plugin for mako
Browse files Browse the repository at this point in the history
  • Loading branch information
xusd320 committed Aug 8, 2024
1 parent cb9e848 commit a737639
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 40 deletions.
58 changes: 57 additions & 1 deletion packages/preset-umi/src/features/mako/mako.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import path from 'path';
import { IApi } from '../../types';
import {
EntryAssets,
extractEntryAssets,
} from '../../utils/extractEntryAssets';
import { isWindows } from '../../utils/platform';

export default (api: IApi) => {
Expand Down Expand Up @@ -45,17 +49,52 @@ export default (api: IApi) => {
enableBy: api.EnableBy.config,
});

// html 处理逻辑
const assets: EntryAssets = {
// Will contain all js and mjs files
js: [],
// Will contain all css files
css: [],
};

api.modifyConfig((memo) => {
// @TODO remove this when mako support windows
if (isWindows) {
memo.mako = false;
process.env.OKAM = '';
}
const makoPlugins = memo.mako?.plugins || [];
if (!api.config.mpa) {
makoPlugins.mako.plugins.push({
name: 'UmiHtmlGenerationMako',
generateEnd: ({ stats }: any) => {
const entryPointFiles = new Set<string>();

for (const chunk of stats.entrypoints['umi'].chunks) {
const files = stats.chunks.find((c: any) => c.id === chunk).files;
for (const file of files) {
entryPointFiles.add(file);
}
}

let entryAssets = extractEntryAssets(Array.from(entryPointFiles));
Object.entries(entryAssets).forEach(([ext, files]) => {
if (!Array.isArray(assets[ext])) {
assets[ext] = [];
}
assets[ext].push(...files);
});
},
});
}
return {
...memo,
mfsu: false,
hmrGuardian: false,
makoPlugins: memo.mako?.plugins || [],
mako: {
...memo.mako,
plugins: makoPlugins,
},
};
});

Expand All @@ -78,4 +117,21 @@ export default (api: IApi) => {
console.error(e);
}
});

api.addHTMLStyles(() => {
const { publicPath } = api.config;
const displayPublicPath = publicPath === 'auto' ? '/' : publicPath;
return assets.css.map((css) => {
return `${displayPublicPath}${css}`;
});
});

api.addHTMLHeadScripts(() => {
const { publicPath } = api.config;
const displayPublicPath = publicPath === 'auto' ? '/' : publicPath;

return assets.js.map((js) => {
return `${displayPublicPath}${js}`;
});
});
};
49 changes: 10 additions & 39 deletions packages/preset-umi/src/features/webpack/webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import type {
Compiler,
} from '@umijs/bundler-webpack/compiled/webpack';
import { IApi } from '../../types';
import {
EntryAssets,
extractEntryAssets,
} from '../../utils/extractEntryAssets';

export default (api: IApi) => {
api.describe({
Expand All @@ -11,7 +15,7 @@ export default (api: IApi) => {
});

// html 处理逻辑
const assets: { js: string[]; css: string[]; [key: string]: string[] } = {
const assets: EntryAssets = {
// Will contain all js and mjs files
js: [],
// Will contain all css files
Expand All @@ -26,45 +30,12 @@ export default (api: IApi) => {
const entryPointFiles = compilation.entrypoints
.get('umi')!
.getFiles();

// Extract paths to .js, .mjs and .css files from the current compilation
const entryPointPublicPathMap: Record<string, boolean> = {};
const extensionRegexp = /\.(css|js|mjs)(\?|$)/;

const UMI_ASSETS_REG = {
js: /^umi(\..+)?\.js$/,
css: /^umi(\..+)?\.css$/,
};

entryPointFiles.forEach((entryPointPublicPath) => {
const extMatch = extensionRegexp.exec(entryPointPublicPath);
// Skip if the public path is not a .css, .mjs or .js file
if (!extMatch) {
return;
}

if (entryPointPublicPath.includes('.hot-update')) {
return;
let entryAssets = extractEntryAssets(entryPointFiles);
Object.entries(entryAssets).forEach(([ext, files]) => {
if (!Array.isArray(assets[ext])) {
assets[ext] = [];
}

// Skip if this file is already known
// (e.g. because of common chunk optimizations)
if (entryPointPublicPathMap[entryPointPublicPath]) {
return;
}

// umi html 默认会注入 不做处理
if (
UMI_ASSETS_REG.js.test(entryPointPublicPath) ||
UMI_ASSETS_REG.css.test(entryPointPublicPath)
) {
return;
}

entryPointPublicPathMap[entryPointPublicPath] = true;
// ext will contain .js or .css, because .mjs recognizes as .js
const ext = extMatch[1] === 'mjs' ? 'js' : extMatch[1];
assets[ext].push(entryPointPublicPath);
assets[ext].push(...files);
});
},
);
Expand Down
60 changes: 60 additions & 0 deletions packages/preset-umi/src/utils/extractEntryAssets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
export type EntryAssets = {
js: string[];
css: string[];
[key: string]: string[];
};

export function extractEntryAssets(entryPointFiles: string[]): EntryAssets {
const assets: {
js: string[];
css: string[];
[key: string]: string[];
} = {
// Will contain all js and mjs files
js: [],
// Will contain all css files
css: [],
};

// Extract paths to .js, .mjs and .css files from the current compilation
const entryPointPublicPathMap: Record<string, boolean> = {};
const extensionRegexp = /\.(css|js|mjs)(\?|$)/;

const UMI_ASSETS_REG = {
js: /^umi(\..+)?\.js$/,
css: /^umi(\..+)?\.css$/,
};

entryPointFiles.forEach((entryPointPublicPath) => {
const extMatch = extensionRegexp.exec(entryPointPublicPath);
// Skip if the public path is not a .css, .mjs or .js file
if (!extMatch) {
return;
}

if (entryPointPublicPath.includes('.hot-update')) {
return;
}

// Skip if this file is already known
// (e.g. because of common chunk optimizations)
if (entryPointPublicPathMap[entryPointPublicPath]) {
return;
}

// umi html 默认会注入 不做处理
if (
UMI_ASSETS_REG.js.test(entryPointPublicPath) ||
UMI_ASSETS_REG.css.test(entryPointPublicPath)
) {
return;
}

entryPointPublicPathMap[entryPointPublicPath] = true;
// ext will contain .js or .css, because .mjs recognizes as .js
const ext = extMatch[1] === 'mjs' ? 'js' : extMatch[1];
assets[ext].push(entryPointPublicPath);
});

return assets;
}

0 comments on commit a737639

Please sign in to comment.