Skip to content

Commit

Permalink
DRAFT: Make esbuild to produce bundle
Browse files Browse the repository at this point in the history
Signed-off-by: Victor Rubezhny <[email protected]>
  • Loading branch information
vrubezhny committed Nov 12, 2024
1 parent 3e6fae3 commit fb6a8c5
Show file tree
Hide file tree
Showing 68 changed files with 1,600 additions and 559 deletions.
60 changes: 33 additions & 27 deletions .vscodeignore
Original file line number Diff line number Diff line change
@@ -1,36 +1,42 @@
.vscode/**
.vscode-test/**
azure-pipelines.yml
build/**
build/**
CONTRIBUTING.md
coverage/**
coverconfig.json
doc/**
.eslintignore
.gitattributes
.github
.gitignore
header.js
images/demo-featured-image.png
images/gif/**
out/test/**
Jenkinsfile
.mocharc.js
out/build**
out/build/**
out/test-resources/**
out/tools-cache/**
out/coverage/**
out/**/*.map
out/src-orig/**
out/test/**
out/test-resources/**
out/tools-cache/**
out/webview/**
*.sha256
src/**
!src/tools.json
doc/**
.gitignore
.github
tsconfig.json
vsc-extension-quickstart.md
tslint.json
*.vsix
test/**
out/coverage/**
coverconfig.json
Jenkinsfile
.gitattributes
.travis.yml
CONTRIBUTING.md
build/**
out/build**
azure-pipelines.yml
images/demo-featured-image.png
test/**
test-resources/**
test-resources/**
header.js
.mocharc.js
.eslintignore
*.tgz
*.sha256
**.tsbuildinfo
.travis.yml
*/**.tsbuildinfo
tsconfig.json
tsconfig.tsbuildinfo
tslint.json
vsc-extension-quickstart.md
.vscode/**
.vscode-test/**
*.vsix
216 changes: 204 additions & 12 deletions build/esbuild.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@
*-----------------------------------------------------------------------------------------------*/

import * as esbuild from 'esbuild';
// import { nodeExternalsPlugin } from 'esbuild-node-externals';
import svgr from 'esbuild-plugin-svgr';
import { sassPlugin } from 'esbuild-sass-plugin';
import * as fs from 'fs/promises';
import * as glob from 'glob';
import { createRequire } from 'module';
import * as path from 'path';
import { fileURLToPath } from 'url';

// const { nodeExternalsPlugin } = require('esbuild-node-externals');
const require = createRequire(import.meta.url);

const webviews = [
'cluster',
Expand All @@ -26,14 +34,140 @@ const webviews = [
'openshift-terminal',
];

await Promise.all([
esbuild.build({
entryPoints: webviews.map(webview => `./src/webview/${webview}/app/index.tsx`),
bundle: true,
outdir: 'out',
const production = process.argv.includes('--production');

// eslint-disable no-console
console.log(`esbuild: building for production: ${production ? 'Yes' : 'No'}`);
// console.log(`esbuild: sync: ${glob.sync(['out/src/**/*.js'])}`);

const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file
const __dirname = path.resolve(path.dirname(__filename), '..'); // get the name of the directory
const srcDir = 'src'; // Input source directory
const outDir = 'out'; // Output dist directory

// console.log(`esbuild: outDir: \t${outDir}`);

function logConfig(cfg) {
console.log(`esbuild: entryPoints: \t${cfg.entryPoints}`);
console.log(`esbuild: bundle: \t${cfg.bundle}`);
console.log(`esbuild: target: \t${cfg.target}`);
console.log(`esbuild: minify: \t${cfg.minify}`);
console.log(`esbuild: sourcemap: \t${cfg.sourcemap}`);
console.log(`esbuild: logLevel: \t${cfg.logLevel}`);
if (cfg.outfile) console.log(`esbuild: outfile: \t${cfg.outfile}`);
if (cfg.outdir) console.log(`esbuild: ourdir: \t${cfg.outdir}`);
}

function detectGoal(entryPoints) {
if (production) {
const isExtension = entryPoints.filter((ep) => `${ep}`.includes('extension.ts')).length > 0;
const isWebviews = entryPoints.filter((ep) => `${ep}`.includes('.tsx')).length > 0;
return isExtension ? 'Extension' : isWebviews ? 'the Webviews' : '';
}
return 'Extension and the Webviews for testing/debugging';
}

/**
* @type {import('esbuild').Plugin}
*/
const esbuildProblemMatcherPlugin = {
name: 'esbuild-problem-matcher',

setup(build) {
build.onStart(() => {
const goal = detectGoal(build.initialOptions.entryPoints);
console.log(`[watch] build started${goal ? ' for ' + goal : ''}...` );
logConfig(build.initialOptions);
});
build.onEnd(result => {
result.errors.forEach(({ text, location }) => {
console.error(`✘ [ERROR] ${text}`);
if (location) {
console.error(` ${location.file}:${location.line}:${location.column}:`);
}
});
const goal = detectGoal(build.initialOptions.entryPoints);
console.log(`[watch] build finished${goal ? ' for ' + goal : ''}`);
});
}
};

const nativeNodeModulesPlugin = {
name: 'native-node-modules',
setup(build) {
try {
// If a ".node" file is imported within a module in the "file" namespace, resolve
// it to an absolute path and put it into the "node-file" virtual namespace.
build.onResolve({ filter: /\.node$/, namespace: 'file' }, args => ({
path: require.resolve(args.path, { paths: [args.resolveDir] }),
namespace: 'node-file',
}));

// Files in the "node-file" virtual namespace call "require()" on the
// path from esbuild of the ".node" file in the output directory.
build.onLoad({ filter: /.*/, namespace: 'node-file' }, args => ({
contents: `
import path from ${JSON.stringify(args.path)}
try {
module.exports = require(path)
} catch {}
`,
}))

// If a ".node" file is imported within a module in the "node-file" namespace, put
// it in the "file" namespace where esbuild's default loading behavior will handle
// it. It is already an absolute path since we resolved it to one above.
build.onResolve({ filter: /\.node$/, namespace: 'node-file' }, args => ({
path: args.path,
namespace: 'file',
}));

// Tell esbuild's default loading behavior to use the "file" loader for
// these ".node" files.
let opts = build.initialOptions
opts.loader = opts.loader || {}
opts.loader['.node'] = 'file'
} catch (err) {
console.error(`native-node-modules: ERROR: ${err}`);
}
},
};

const baseConfig = {
bundle: true,
target: 'chrome108',
minify: production,
sourcemap: !production,
logLevel: 'warning',
};

// console.log(`esbuild: bundle: \t${baseConfig.bundle}`);
// console.log(`esbuild: target: \t${baseConfig.target}`);
// console.log(`esbuild: minify: \t${baseConfig.minify}`);
// console.log(`esbuild: sourcemap: \t${baseConfig.sourcemap}`);
// console.log(`esbuild: logLevel: \t${baseConfig.logLevel}`);
if (production) {
// Build the extension.js
const extConfig = {
...baseConfig,
platform: 'node',
entryPoints: [`./${srcDir}/extension.ts`],
outfile: `${outDir}/${srcDir}/extension.js`,
external: ['vscode', 'shelljs'],
plugins: [
nativeNodeModulesPlugin,
esbuildProblemMatcherPlugin // this one is to be added to the end of plugins array
]
};

await esbuild.build(extConfig);

// Build the Webviews
const webviewsConfig = {
...baseConfig,
platform: 'browser',
target: 'chrome108',
sourcemap: true,
entryPoints: [...webviews.map(webview => `./${srcDir}/webview/${webview}/app/index.tsx`)],
outdir: `${outDir}`,
loader: {
'.png': 'file',
},
Expand All @@ -42,9 +176,67 @@ await Promise.all([
svgr({
plugins: ['@svgr/plugin-jsx']
}),
esbuildProblemMatcherPlugin // this one is to be added to the end of plugins array
]
}),
...webviews.map(webview =>
fs.cp(`./src/webview/${webview}/app/index.html`, `./out/${webview}/app/index.html`)
),
]);
};
await esbuild.build(webviewsConfig);
} else {
// Build the extension.js
// const extConfig = {
// ...baseConfig,
// bundle: false,
// platform: 'node',
// entryPoints: [`./${outDir}/${srcDir}/extension.js`],
// outdir: `${outDir}`,
// // external: ['vscode', 'shelljs'],
// plugins: [
// nativeNodeModulesPlugin,
// esbuildProblemMatcherPlugin // this one is to be added to the end of plugins array
// ]
// };

// await esbuild.build(extConfig);

const devConfig = {
...baseConfig,
platform: 'browser',
entryPoints: [...webviews.map(webview => `./${srcDir}/webview/${webview}/app/index.tsx`)],
outdir: `${outDir}`,
loader: {
'.png': 'file',
},
plugins: [
sassPlugin(),
svgr({
plugins: ['@svgr/plugin-jsx']
}),
esbuildProblemMatcherPlugin // this one is to be added to the end of plugins array
]
};
await esbuild.build(devConfig);
}

async function dirExists(path) {
try {
if ((await fs.stat(path)).isDirectory()) {
return true;
}
} catch {
// Ignore
}
return false;
}

// Copy webview's 'index.html's to the output webview dirs
await Promise.all([
...webviews.map(async webview => {
const targetDir = path.join(__dirname, `${outDir}/${webview}/app`);
if (!dirExists(targetDir)) {
await fs.mkdir(targetDir, { recursive: true, mode: 0o750} );
}
glob.sync([ `${srcDir}/webview/${webview}/app/index.html` ]).map(async srcFile => {
// console.log(`esbuild: copying: ${path.join(__dirname, srcFile)} ==>> ${path.join(targetDir, `${path.basename(srcFile)}`)}`);
await fs.cp(path.join(__dirname, srcFile), path.join(targetDir, `${path.basename(srcFile)}`))
});
})
]);
21 changes: 19 additions & 2 deletions build/run-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ async function main(): Promise<void> {
const integrationWorkspacePath = path.resolve(extensionRootPath, 'test', 'fixtures', 'components', 'components.code-workspace');
const unitTestWorkspacePath = path.resolve(extensionRootPath, 'test', 'fixtures', 'components', 'empty.code-workspace');
try {

/* eslint-disable no-console */
console.error(`run-tests#main: __dirname: '${__dirname}'`);
console.error(`run-tests#main: tests: '${tests}'`);
console.error(`run-tests#main: extension: '${extension}'`);
console.error(`run-tests#main: extensionRootPath: '${extensionRootPath}'`);
console.error(`run-tests#main: extensionDevelopmentPath: '${extensionDevelopmentPath}'`);
console.error(`run-tests#main: extensionTestsPath: '${extensionTestsPath}'`);
console.error(`run-tests#main: integrationWorkspacePath: '${integrationWorkspacePath}'`);
console.error(`run-tests#main: unitTestWorkspacePath: '${unitTestWorkspacePath}'`);
console.error('');
console.error(`run-tests#main: launchArgs: '${([
tests === 'integration' ? integrationWorkspacePath : unitTestWorkspacePath,
'--disable-workspace-trust',
])}'`);
/* eslint-disable no-console */

await etest.runTests({
extensionDevelopmentPath,
extensionTestsPath,
Expand All @@ -27,9 +44,9 @@ async function main(): Promise<void> {
'--disable-workspace-trust',
],
});
} catch {
} catch (err) {
// eslint-disable-next-line no-console
console.error('Failed to run tests');
console.error(`Failed to run tests: ${err}`);
process.exit(1);
}
}
Expand Down
Loading

0 comments on commit fb6a8c5

Please sign in to comment.