Skip to content
This repository has been archived by the owner on Nov 17, 2022. It is now read-only.

Commit

Permalink
feat: pre bundle dependencies (#466)
Browse files Browse the repository at this point in the history
* feat: precompile unplugin

* feat: prebundle mini-css-extract-plugin

* chore: update lock

* chore: update webpack version

* chore: update dependencies

* chore: update terser version

* fix: update lock

* fix: prepack webpack-dev-server

* feat: prebundle react-refresh-webpack-plugin

* fix: optimize code

* fix: prepack

* fix: source map error

* fix: update scripts
  • Loading branch information
ClarkXia authored Aug 31, 2022
1 parent 40ce2a5 commit 5d10f02
Show file tree
Hide file tree
Showing 16 changed files with 701 additions and 727 deletions.
18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
"build": "pnpm run clean && pnpm -r --filter=./packages/* run build",
"prebundle": "cd packages/bundles && pnpm build",
"clean": "rimraf packages/*/esm",
"dependency:check": "esmo ./scripts/dependencyCheck.ts",
"version": "esmo ./scripts/tagVersion.ts",
"version:check": "esmo ./scripts/versionCheck.ts",
"dependency:check": "tsx ./scripts/dependencyCheck.ts",
"version": "tsx ./scripts/tagVersion.ts",
"version:check": "tsx ./scripts/versionCheck.ts",
"lint": "eslint --cache --ext .js,.jsx,.ts,.tsx ./",
"publish:alpha": "PUBLISH_TYPE=alpha esmo ./scripts/publishPackageWithDistTag.ts",
"publish:beta": "PUBLISH_TYPE=beta esmo ./scripts/publishPackageWithDistTag.ts",
"publish:release": "PUBLISH_TYPE=release VERSION_PREFIX=rc esmo ./scripts/publishPackageWithDistTag.ts",
"publish:alpha": "PUBLISH_TYPE=alpha tsx ./scripts/publishPackageWithDistTag.ts",
"publish:beta": "PUBLISH_TYPE=beta tsx ./scripts/publishPackageWithDistTag.ts",
"publish:release": "PUBLISH_TYPE=release VERSION_PREFIX=rc tsx ./scripts/publishPackageWithDistTag.ts",
"cov": "vitest run --coverage",
"test": "vitest"
},
Expand All @@ -34,15 +34,14 @@
"@types/fs-extra": "^9.0.13",
"@types/glob": "^7.2.0",
"@types/node": "^17.0.45",
"@types/semver": "^7.3.11",
"@types/semver": "^7.3.12",
"@vercel/ncc": "^0.33.4",
"c8": "^7.12.0",
"chalk": "^4.1.2",
"chokidar": "^3.5.3",
"dependency-check": "^4.1.0",
"dts-bundle": "^0.7.3",
"eslint": "^8.21.0",
"esno": "^0.14.1",
"eslint": "^8.22.0",
"execa": "^6.1.0",
"find-up": "^5.0.0",
"fs-extra": "^10.1.0",
Expand All @@ -59,6 +58,7 @@
"rimraf": "^3.0.2",
"semver": "^7.3.7",
"stylelint": "^14.10.0",
"tsx": "^3.9.0",
"typescript": "^4.7.4",
"vitest": "^0.15.2"
},
Expand Down
48 changes: 40 additions & 8 deletions packages/bundles/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,24 @@
],
"scripts": {
"watch": "tsc -w",
"build": "esmo scripts/build.ts && tsc"
"build": "tsx scripts/build.ts && tsc"
},
"main": "./esm/index.js",
"type": "module",
"dependencies": {
"ansi-html-community": "^0.0.8",
"html-entities": "^2.3.2",
"@swc/core": "1.2.210",
"caniuse-lite": "^1.0.30001332",
"chokidar": "3.5.3",
"events": "3.3.0",
"jest-worker": "27.5.1",
"less": "4.1.2",
"postcss": "8.4.12",
"sass": "1.50.0"
"sass": "1.50.0",
"react-refresh": "0.14.0",
"core-js-pure": "^3.8.1",
"error-stack-parser": "^2.0.6"
},
"devDependencies": {
"@types/cacache": "^15.0.1",
Expand All @@ -41,7 +46,7 @@
"fs-extra": "^10.0.0",
"less-loader": "10.2.0",
"lodash": "4.17.21",
"mini-css-extract-plugin": "2.6.0",
"mini-css-extract-plugin": "2.6.1",
"ora": "5.4.1",
"postcss-loader": "6.2.1",
"postcss-modules": "4.3.1",
Expand All @@ -50,12 +55,39 @@
"postcss-preset-env": "7.4.3",
"sass-loader": "12.6.0",
"tapable": "2.2.1",
"terser": "5.12.1",
"terser-webpack-plugin": "5.3.1",
"terser": "5.14.2",
"terser-webpack-plugin": "5.3.5",
"typescript": "^4.6.4",
"webpack": "5.73.0",
"webpack": "5.74.0",
"webpack-bundle-analyzer": "4.5.0",
"webpack-dev-server": "4.8.1",
"webpack-sources": "3.2.3"
"webpack-dev-server": "4.10.0",
"webpack-sources": "3.2.3",
"unplugin": "0.9.5",
"bonjour-service": "^1.0.13",
"colorette": "^2.0.10",
"compression": "^1.7.4",
"connect-history-api-fallback": "^1.6.0",
"default-gateway": "^6.0.3",
"express": "^4.17.3",
"graceful-fs": "^4.2.6",
"http-proxy-middleware": "^2.0.3",
"ipaddr.js": "^2.0.1",
"open": "^8.0.9",
"p-retry": "^4.5.0",
"portfinder": "^1.0.28",
"rimraf": "^3.0.2",
"schema-utils": "^4.0.0",
"selfsigned": "^2.0.1",
"serve-index": "^1.9.1",
"sockjs": "^0.3.21",
"spdy": "^4.0.2",
"webpack-dev-middleware": "^5.3.1",
"ws": "^8.4.2",
"globby": "13.1.2",
"@pmmmwh/react-refresh-webpack-plugin": "0.5.7",
"loader-utils": "^2.0.0",
"source-map": "0.8.0-beta.0",
"find-up": "5.0.0",
"common-path-prefix": "3.0.0"
}
}
99 changes: 51 additions & 48 deletions packages/bundles/scripts/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ interface Options {
declaration?: boolean;
bundleName?: string;
emptyDir?: boolean;
skipCompile?: boolean;
matchCopyFiles?: (data: {
resolvePath: string;
resolveId: string;
Expand All @@ -35,7 +36,7 @@ interface Options {

export async function packDependency(options: Options): Promise<void> {
const { pkgName, file, rootDir, target, externals, matchCopyFiles, patch, emptyDir = true,
bundleName = 'index.js', minify = true, declaration = true } = options;
bundleName = 'index.js', minify = true, declaration = true, skipCompile } = options;
console.log(chalk.green(`start pack ${pkgName || file}`));

const targetPath = path.join(rootDir, target);
Expand All @@ -48,58 +49,60 @@ export async function packDependency(options: Options): Promise<void> {
});

fs.ensureDirSync(targetPath);
const { code, assets } = await ncc(packEntry, {
cache: false,
externals,
minify,
target: 'es5',
assetsBuilds: false,
customEmit(filePath: string, opts: {id: string}) {
const { id } = opts;
if (matchCopyFiles && matchCopyFiles({
resolvePath: filePath,
resolveId: id,
})) {
filesToCopy.push(require.resolve(filePath, {
paths: [path.dirname(id)],
}));
if (!skipCompile) {
const { code, assets } = await ncc(packEntry, {
cache: false,
externals,
minify,
target: 'es5',
assetsBuilds: false,
customEmit(filePath: string, opts: {id: string}) {
const { id } = opts;
if (matchCopyFiles && matchCopyFiles({
resolvePath: filePath,
resolveId: id,
})) {
filesToCopy.push(require.resolve(filePath, {
paths: [path.dirname(id)],
}));

return `'./${path.basename(filePath)}'`;
return `'./${path.basename(filePath)}'`;
}
},
});
for (const assetKey of Object.keys(assets)) {
const asset = assets[assetKey];
const data = asset.source;
const fileTarget = path.join(targetPath, assetKey);
fs.ensureDirSync(path.dirname(fileTarget));
fs.writeFileSync(fileTarget, data);
}
// copy files
for (const fileToCopy of filesToCopy) {
let content = fs.readFileSync(fileToCopy, 'utf-8');
for (const key of Object.keys(externals)) {
content = content.replace(
new RegExp(`require\\(['"]${key}['"]\\)`, 'gm'),
`require('${externals[key]}')`,
);
content = content.replace(
new RegExp(`require\\(['"]${key}/package(.json)?['"]\\)`, 'gm'),
`require('${externals[key]}/package.json')`,
);
}
},
});
for (const assetKey of Object.keys(assets)) {
const asset = assets[assetKey];
const data = asset.source;
const fileTarget = path.join(targetPath, assetKey);
fs.ensureDirSync(path.dirname(fileTarget));
fs.writeFileSync(fileTarget, data);
}
// copy files
for (const fileToCopy of filesToCopy) {
let content = fs.readFileSync(fileToCopy, 'utf-8');
for (const key of Object.keys(externals)) {
content = content.replace(
new RegExp(`require\\(['"]${key}['"]\\)`, 'gm'),
`require('${externals[key]}')`,
);
content = content.replace(
new RegExp(`require\\(['"]${key}/package(.json)?['"]\\)`, 'gm'),
`require('${externals[key]}/package.json')`,
const copyTarget = path.join(targetPath, path.basename(fileToCopy));
console.log(chalk.green(`fileToCopy ${copyTarget}`));
fs.writeFileSync(
copyTarget,
content,
'utf-8',
);
}
const copyTarget = path.join(targetPath, path.basename(fileToCopy));
console.log(chalk.green(`fileToCopy ${copyTarget}`));
fs.writeFileSync(
copyTarget,
content,
'utf-8',
);
// write code to package
const outfile = path.join(targetPath, bundleName);
fs.ensureDirSync(path.dirname(outfile));
fs.writeFileSync(path.join(targetPath, bundleName), code, 'utf-8');
}
// write code to package
const outfile = path.join(targetPath, bundleName);
fs.ensureDirSync(path.dirname(outfile));
fs.writeFileSync(path.join(targetPath, bundleName), code, 'utf-8');
if (pkgName) {
const packageRoot = path.dirname(
findUp.sync('package.json', {
Expand Down
104 changes: 94 additions & 10 deletions packages/bundles/scripts/tasks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs-extra';
import { globbySync } from 'globby';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

Expand All @@ -18,17 +19,28 @@ export const taskExternals = {
postcss: 'postcss',
'@swc/core': '@swc/core',
'jest-worker': 'jest-worker',
terser: '@ice/bundles/compiled/terser',
tapable: '@ice/bundles/compiled/tapable',
cssnano: '@ice/bundles/compiled/cssnano',
// depend by webpack
'terser-webpack-plugin': '@ice/bundles/compiled/terser-webpack-plugin',
webpack: '@ice/bundles/compiled/webpack',
'schema-utils': '@ice/bundles/compiled/schema-utils',
lodash: '@ice/bundles/compiled/lodash',
'postcss-preset-env': '@ice/bundles/compiled/postcss-preset-env',
};

const commonDeps = ['terser', 'tapable', 'cssnano', 'terser-webpack-plugin', 'webpack', 'schema-utils',
'lodash', 'postcss-preset-env', 'loader-utils', 'find-up', 'common-path-prefix'];

const webpackDevServerDeps = ['bonjour-service', 'colorette', 'compression', 'connect-history-api-fallback',
'default-gateway', 'express', 'graceful-fs', 'http-proxy-middleware',
'ipaddr.js', 'open', 'p-retry', 'portfinder', 'rimraf', 'selfsigned', 'serve-index',
'sockjs', 'spdy', 'webpack-dev-middleware', 'ws'];

commonDeps.concat(webpackDevServerDeps).forEach(dep => taskExternals[dep] = `@ice/bundles/compiled/${dep}`);

function replaceDeps(code: string, deps: string[]) {
return deps.reduce((acc, curr) => {
return acc
// cjs
.replace(new RegExp(`require\\(["']${curr}["']\\)`, 'g'), `require("${`@ice/bundles/compiled/${curr}`}")`)
// esm
.replace(new RegExp(`from ["']${curr}["']`, 'g'), `from "${`@ice/bundles/compiled/${curr}`}"`);
}, code);
}

export function filterExternals(externals: Record<string, string>, keys: string[]) {
const filterExternals = {};
Object.keys(externals).forEach((externalKey) => {
Expand All @@ -45,8 +57,26 @@ const tasks = [
'less-loader', 'postcss-loader', 'sass-loader', 'css-loader',
'postcss-preset-env', 'postcss-nested', 'postcss-modules', 'postcss-plugin-rpx2vw',
'webpack-bundle-analyzer', 'es-module-lexer', 'terser',
'eslint-webpack-plugin', 'copy-webpack-plugin', 'cacache', 'ora',
'eslint-webpack-plugin', 'copy-webpack-plugin', 'cacache', 'ora', 'unplugin',
// Dependencies of react-refresh-webpack-plugin.
'loader-utils', 'source-map', 'find-up', 'common-path-prefix',
// Dependencies of webpack-dev-server.
...webpackDevServerDeps,
].map((pkgName) => ({ pkgName })),
{
pkgName: 'unplugin',
declaration: false,
emptyDir: false,
file: 'node_modules/unplugin/dist/webpack/loaders/transform.js',
bundleName: 'webpack/loaders/transform.js',
},
{
pkgName: 'unplugin',
declaration: false,
emptyDir: false,
file: 'node_modules/unplugin/dist/webpack/loaders/load.js',
bundleName: 'webpack/loaders/load.js',
},
{
// pack main package
pkgName: 'fork-ts-checker-webpack-plugin',
Expand Down Expand Up @@ -74,13 +104,67 @@ const tasks = [
return resolvePath.includes('./utils') && resolveId.includes('css-minimizer-webpack-plugin/dist');
},
},
{
pkgName: 'mini-css-extract-plugin',
skipCompile: true,
patch: () => {
// copy packages
const pkgPath = path.join(__dirname, '../node_modules/mini-css-extract-plugin');
const targetPath = path.join(__dirname, '../compiled/mini-css-extract-plugin');
const entryPath = path.join(targetPath, 'dist/index.js');
fs.copySync(path.join(pkgPath, 'dist'), path.join(targetPath, 'dist'));
fs.copyFileSync(path.join(targetPath, 'index.d.ts'), path.join(targetPath, 'dist/index.d.ts'));
fs.writeFileSync(entryPath, fs.readFileSync(entryPath, 'utf-8').replace('schema-utils', '@ice/bundles/compiled/schema-utils/index.js'));
},
},
{
pkgName: 'terser-webpack-plugin',
matchCopyFiles: (data: { resolvePath: string; resolveId: string }): boolean => {
const { resolvePath } = data;
return resolvePath.endsWith('./utils') || resolvePath.endsWith('.json');
},
},
{
pkgName: 'webpack-dev-server',
skipCompile: true,
patch: () => {
// Copy webpack-dev-server while all dependencies has been packed.
const pkgPath = path.join(__dirname, '../node_modules/webpack-dev-server');
const filePaths = globbySync(['**/*'], { cwd: pkgPath, ignore: ['node_modules', 'types', 'bin'] });
filePaths.forEach((filePath) => {
fs.ensureDirSync(path.join(__dirname, `../compiled/webpack-dev-server/${path.dirname(filePath)}`));
const sourcePath = path.join(pkgPath, filePath);
const targetPath = path.join(__dirname, `../compiled/webpack-dev-server/${filePath}`);
if (path.extname(filePath) === '.js') {
const fileContent = fs.readFileSync(sourcePath, 'utf8');
fs.writeFileSync(targetPath, replaceDeps(fileContent, webpackDevServerDeps.concat(commonDeps)));
} else {
fs.copyFileSync(sourcePath, targetPath);
}
});
},
},
{
pkgName: '@pmmmwh/react-refresh-webpack-plugin',
skipCompile: true,
patch: () => {
// Copy @pmmmwh/react-refresh-webpack-plugin while all dependencies has been packed.
const pkgPath = path.join(__dirname, '../node_modules/@pmmmwh/react-refresh-webpack-plugin');
const filePaths = globbySync(['**/*'], { cwd: pkgPath, ignore: ['node_modules', 'types'] });
filePaths.forEach((filePath) => {
fs.ensureDirSync(path.join(__dirname, `../compiled/@pmmmwh/react-refresh-webpack-plugin/${path.dirname(filePath)}`));
const sourcePath = path.join(pkgPath, filePath);
const targetPath = path.join(__dirname, `../compiled/@pmmmwh/react-refresh-webpack-plugin/${filePath}`);
if (path.extname(filePath) === '.js') {
const fileContent = fs.readFileSync(sourcePath, 'utf8');
// Add source-map for react-refresh-webpack-plugin, while other dependencies should pack it.
fs.writeFileSync(targetPath, replaceDeps(fileContent, commonDeps.concat('source-map')));
} else {
fs.copyFileSync(sourcePath, targetPath);
}
});
},
},
{
file: './webpack/bundle',
pkgName: 'webpack',
Expand Down
Loading

1 comment on commit 5d10f02

@vercel
Copy link

@vercel vercel bot commented on 5d10f02 Aug 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

ice-v3 – ./

ice-v3-git-release-next-ice-v3.vercel.app
ice-v3.vercel.app
ice-v3-ice-v3.vercel.app

Please sign in to comment.