Skip to content

Commit

Permalink
Merge pull request #991 from ckeditor/fix-source-maps-in-umd-build
Browse files Browse the repository at this point in the history
Fix (build-tools): Fixed source maps generation for the UMD build. Fixes ckeditor/ckeditor5#16984.

Feature (build-tools): Introduced a new `loadSourcemaps` plugin for loading source maps of external dependencies.
  • Loading branch information
filipsobol authored Aug 28, 2024
2 parents 6f5a467 + 4ad052e commit defb966
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 43 deletions.
29 changes: 22 additions & 7 deletions packages/ckeditor5-dev-build-tools/src/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import util from 'util';
import chalk from 'chalk';
import path from 'upath';
import { rollup, type RollupOutput, type GlobalsOption } from 'rollup';
import { loadSourcemaps } from './plugins/loadSourcemaps.js';
import { getRollupConfig } from './config.js';
import { getCwdPath, camelizeObjectKeys, removeWhitespace } from './utils.js';
import { getCwdPath, camelizeObjectKeys, removeWhitespace, getOptionalPlugin } from './utils.js';

export interface BuildOptions {
input: string;
Expand Down Expand Up @@ -104,19 +105,33 @@ async function generateUmdBuild( args: BuildOptions, bundle: RollupOutput ): Pro

const { dir, name } = path.parse( args.output );
const { plugins, ...config } = await getRollupConfig( args );
const build = await rollup( config );
const globals = {
...CKEDITOR_GLOBALS,
...args.globals as GlobalsOption
};

/**
* Ignore the plugins we used for the ESM build. Instead, add a new plugin to not only
* load the source code of the dependencies (which is the default in Rollup for better
* performance), but also their source maps to generate a proper final source map for
* the UMD bundle.
*/
const build = await rollup( {
...config,
plugins: [
getOptionalPlugin(
args.sourceMap,
loadSourcemaps()
)
]
} );

const umdBundle = await build.write( {
format: 'umd',
file: path.join( dir, `${ name }.umd.js` ),
assetFileNames: '[name][extname]',
sourcemap: args.sourceMap,
name: args.name,
globals
globals: {
...CKEDITOR_GLOBALS,
...args.globals as GlobalsOption
}
} );

return {
Expand Down
11 changes: 2 additions & 9 deletions packages/ckeditor5-dev-build-tools/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

import path from 'upath';
import { existsSync } from 'fs';
import { getUserDependency } from './utils.js';
import { getOptionalPlugin, getUserDependency } from './utils.js';
import type { PackageJson } from 'type-fest';
import type { InputPluginOption, Plugin, RollupOptions } from 'rollup';
import type { Plugin, RollupOptions } from 'rollup';
import type { BuildOptions } from './build.js';

/**
Expand Down Expand Up @@ -272,13 +272,6 @@ export async function getRollupConfig( options: BuildOptions ) {
} as const satisfies RollupOptions;
}

/**
* Returns plugin if condition is truthy. This is used only to get the types right.
*/
function getOptionalPlugin<T extends InputPluginOption>( condition: unknown, plugin: T ): T | undefined {
return condition ? plugin : undefined;
}

/**
* Returns a list of keys in `package.json` file of a given dependency.
*/
Expand Down
1 change: 1 addition & 0 deletions packages/ckeditor5-dev-build-tools/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
export { build } from './build.js';
export { addBanner, type RollupBannerOptions } from './plugins/banner.js';
export { emitCss, type RollupEmitCssOptions } from './plugins/emitCss.js';
export { loadSourcemaps } from './plugins/loadSourcemaps.js';
export { replaceImports, type RollupReplaceOptions } from './plugins/replace.js';
export { splitCss, type RollupSplitCssOptions } from './plugins/splitCss.js';
export { translations, type RollupTranslationsOptions } from './plugins/translations.js';
25 changes: 25 additions & 0 deletions packages/ckeditor5-dev-build-tools/src/plugins/loadSourcemaps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md.
*/

import fs from 'fs';
import type { Plugin } from 'rollup';

export function loadSourcemaps(): Plugin {
return {
name: 'cke5-load-sourcemaps',
load( id: string ) {
const sourceMapId = id + '.map';

if ( !fs.existsSync( sourceMapId ) ) {
return;
}

return {
code: fs.readFileSync( id, 'utf-8' ),
map: fs.readFileSync( sourceMapId, 'utf-8' )
};
}
};
}
8 changes: 8 additions & 0 deletions packages/ckeditor5-dev-build-tools/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { createRequire } from 'module';
import path from 'upath';
import type { CamelCase, CamelCasedProperties } from 'type-fest';
import type { InputPluginOption } from 'rollup';

const require = createRequire( import.meta.url );

Expand Down Expand Up @@ -60,3 +61,10 @@ export function getUserDependency( name: string ): any {

return require( path );
}

/**
* Returns plugin if condition is truthy. This is used only to get the types right.
*/
export function getOptionalPlugin<T extends InputPluginOption>( condition: unknown, plugin: T ): T | undefined {
return condition ? plugin : undefined;
}
20 changes: 19 additions & 1 deletion packages/ckeditor5-dev-build-tools/tests/_utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
*/

import { expect, vi } from 'vitest';
import type { RollupOutput, OutputChunk, OutputAsset } from 'rollup';
import swc from '@rollup/plugin-swc';
import type { RollupOutput, OutputChunk, OutputAsset, Plugin } from 'rollup';
import * as utils from '../../src/utils';

/**
Expand Down Expand Up @@ -71,3 +72,20 @@ export async function mockGetUserDependency( path: string, cb: () => any ): Prom
return actualImport( url );
} );
}

/**
* Helper function for getting a preconfigured `swc` plugin.
*/
export function swcPlugin(): Plugin {
return swc( {
include: [ '**/*.[jt]s' ],
swc: {
jsc: {
target: 'es2019'
},
module: {
type: 'es6'
}
}
} );
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@

import { join } from 'path';
import { test, expect } from 'vitest';
import swc from '@rollup/plugin-swc';
import styles from 'rollup-plugin-styles';
import { rollup, type RollupOutput, type OutputAsset } from 'rollup';
import { verifyAsset, verifyChunk } from '../../_utils/utils.js';
import { swcPlugin, verifyAsset, verifyChunk } from '../../_utils/utils.js';

import { addBanner, type RollupBannerOptions } from '../../../src/index.js';

Expand All @@ -19,17 +18,7 @@ async function generateBundle( options: RollupBannerOptions, sourcemap: boolean
const bundle = await rollup( {
input: join( import.meta.dirname, './fixtures/input.ts' ),
plugins: [
swc( {
include: [ '**/*.[jt]s' ],
swc: {
jsc: {
target: 'es2019'
},
module: {
type: 'es6'
}
}
} ),
swcPlugin,

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,17 @@

import { join } from 'path';
import { test } from 'vitest';
import swc from '@rollup/plugin-swc';
import styles from 'rollup-plugin-styles';
import { rollup, type RollupOutput } from 'rollup';
import { verifyAsset } from '../../_utils/utils.js';
import { swcPlugin, verifyAsset } from '../../_utils/utils.js';

import { emitCss } from '../../../src/index.js';

async function generateBundle( input: string ): Promise<RollupOutput['output']> {
const bundle = await rollup( {
input: join( import.meta.dirname, input ),
plugins: [
swc( {
include: [ '**/*.[jt]s' ],
swc: {
jsc: {
target: 'es2019'
},
module: {
type: 'es6'
}
}
} ),
swcPlugin,

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md.
*/

// The `magic-string` package is used because it contains source maps.
export { default as MagicString } from 'magic-string';
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": [
"ES2022",
"DOM",
"DOM.Iterable"
],
"module": "NodeNext",
"moduleResolution": "NodeNext",
"skipLibCheck": true,
"resolveJsonModule": true
},
"include": [
"**/*"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md.
*/

import { join } from 'path';
import { test, expect } from 'vitest';
import { rollup, type RollupOutput, type OutputAsset } from 'rollup';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import { swcPlugin } from '../../_utils/utils.js';

import { loadSourcemaps } from '../../../src/index.js';
import { getOptionalPlugin } from '../../../src/utils.js';

async function generateBundle( input: string, sourcemap: boolean = false ): Promise<RollupOutput[ 'output' ]> {
const bundle = await rollup( {
input: join( import.meta.dirname, input ),
plugins: [
nodeResolve(),
swcPlugin,
getOptionalPlugin( sourcemap, loadSourcemaps() )
]
} );

const { output } = await bundle.generate( {
format: 'esm',
file: 'input.js',
assetFileNames: '[name][extname]',
sourcemap
} );

return output;
}

test( 'Emits source maps combined with source maps of dependencies', async () => {
const output = await generateBundle( './fixtures/input.ts', true );
const sourceMap = output.find( asset => asset.fileName === 'input.js.map' ) as OutputAsset;

/**
* The resulting source map will only contain the `/magic-string/src/` string if the source map
* of the `magic-string` dependency was loaded and combined with the source map of the input file.
* Otherwise, the source map will contain the `/magic-string/dist/` string, which is the bundled
* build of the `magic-string` dependency.
*/
expect( sourceMap.source ).toContain( '/magic-string/src/' );
} );

0 comments on commit defb966

Please sign in to comment.