build-system/tasks/helpers.js
/**
 * Transforms a given JavaScript file entry point with esbuild and babel, and
 * watches it for changes (if required).
 *
 * @param {string} srcDir
 * @param {string} srcFilename
 * @param {string} destDir
 * @param {?Object} options
 * @return {!Promise}
 */
Transforms a given JavaScript file entry point with esbuild and babel, and
watches it for changes (if required).


Transforms a given JavaScript file entry point with esbuild and babel and watches it for changes ( if required ) .
async function esbuildCompile(srcDir, srcFilename, destDir, options) {
  const startTime = Date.now();
  const entryPoint = path.join(srcDir, srcFilename);
  const filename = options.minify
    ? options.minifiedName
    : options.toName ?? srcFilename;
  const destFilename = maybeToEsmName(filename);
  const destFile = path.join(destDir, destFilename);
  if (watchedTargets.has(entryPoint)) {
    return watchedTargets.get(entryPoint).rebuild();
  }
  function splitWrapper() {
    const wrapper = options.wrapper ?? wrappers.none;
    const sentinel = '<%= contents %>';
    const start = wrapper.indexOf(sentinel);
    return {
      banner: {js: wrapper.slice(0, start)},
      footer: {js: wrapper.slice(start + sentinel.length)},
    };
  }
  const {banner, footer} = splitWrapper();
  const config = await getAmpConfigForFile(destFilename, options);
  const compiledFile = await getCompiledFile(srcFilename);
  banner.js = config + banner.js + compiledFile;
  const babelCaller =
    options.babelCaller ?? (options.minify ? 'minified' : 'unminified');
  const babelPlugin = getEsbuildBabelPlugin(
    babelCaller,
     true
  );
  const plugins = [babelPlugin];
  if (options.remapDependencies) {
    plugins.unshift(remapDependenciesPlugin());
  }
  let result = null;
  async function build(startTime) {
    if (!result) {
      result = await esbuild.build({
        entryPoints: [entryPoint],
        bundle: true,
        sourcemap: true,
        outfile: destFile,
        define: experimentDefines,
        plugins,
        format: options.outputFormat,
        banner,
        footer,
        target: argv.esm ? 'es6' : 'es5',
        incremental: !!options.watch,
        logLevel: 'silent',
        external: options.externalDependencies,
        mainFields: ['module', 'browser', 'main'],
        write: false,
      });
    } else {
      result = await result.rebuild();
    }
    let code = result.outputFiles.find(({path}) => !path.endsWith('.map')).text;
    let map = result.outputFiles.find(({path}) => path.endsWith('.map')).text;
    if (options.minify) {
      ({code, map} = await minify(code, map));
      map = await massageSourcemaps(map, options);
    }
    await Promise.all([
      fs.outputFile(destFile, code),
      fs.outputFile(`${destFile}.map`, map),
    ]);
    await finishBundle(destDir, destFilename, options, startTime);
  }
  function remapDependenciesPlugin() {
    const remaps = Object.entries(options.remapDependencies).map(
      ([path, value]) => ({regex: new RegExp(`^${path}$`), value})
    );
    const external = options.externalDependencies;
    return {
      name: 'remap-dependencies',
      setup(build) {
        build.onResolve({filter: /.*/}, (args) => {
          const {path: importPath, resolveDir} = args;
          const dep = importPath.startsWith('.')
            ? path.posix.join(resolveDir, importPath)
            : importPath;
          for (const {regex, value} of remaps) {
            if (!regex.test(dep)) {
              continue;
            }
            const isExternal = external.includes(value);
            return {
              path: isExternal ? value : require.resolve(value),
              external: isExternal,
            };
          }
        });
      },
    };
  }
  await build(startTime).catch((err) =>
    handleBundleError(err, !!options.watch, destFilename)
  );
  if (options.watch) {
    watchedTargets.set(entryPoint, {
      rebuild: async () => {
        const startTime = Date.now();
        const buildPromise = build(startTime).catch((err) =>
          handleBundleError(err, !!options.watch, destFilename)
        );
        if (options.onWatchBuild) {
          options.onWatchBuild(buildPromise);
        }
        await buildPromise;
      },
    });
  }
}
async function esbuildCompile ( srcDir , srcFilename , destDir , options ) { const startTime = Date . now ( ) ; const entryPoint = path . join ( srcDir , srcFilename ) ; const filename = options . minify ? options . minifiedName : options . toName ?? srcFilename ; const destFilename = maybeToEsmName ( filename ) ; const destFile = path . join ( destDir , destFilename ) ; if ( watchedTargets . has ( entryPoint ) ) { return watchedTargets . get ( entryPoint ) . rebuild ( ) ; } function splitWrapper ( ) { const wrapper = options . wrapper ?? wrappers . none ; const sentinel = '<%= contents %>' ; const start = wrapper . indexOf ( sentinel ) ; return { banner : { js : wrapper . slice ( 0 , start ) } , footer : { js : wrapper . slice ( start + sentinel . length ) } , } ; } const { banner , footer } = splitWrapper ( ) ; const config = await getAmpConfigForFile ( destFilename , options ) ; const compiledFile = await getCompiledFile ( srcFilename ) ; banner . js = config + banner . js + compiledFile ; const babelCaller = options . babelCaller ?? ( options . minify ? 'minified' : 'unminified' ) ; const babelPlugin = getEsbuildBabelPlugin ( babelCaller , true ) ; const plugins = [ babelPlugin ] ; if ( options . remapDependencies ) { plugins . unshift ( remapDependenciesPlugin ( ) ) ; } let result = null ; async function build ( startTime ) { if ( ! result ) { result = await esbuild . build ( { entryPoints : [ entryPoint ] , bundle : true , sourcemap : true , outfile : destFile , define : experimentDefines , plugins , format : options . outputFormat , banner , footer , target : argv . esm ? 'es6' : 'es5' , incremental : ! ! options . watch , logLevel : 'silent' , external : options . externalDependencies , mainFields : [ 'module' , 'browser' , 'main' ] , write : false , } ) ; } else { result = await result . rebuild ( ) ; } let code = result . outputFiles . find ( ( { path } ) => ! path . endsWith ( '.map' ) ) . text ; let map = result . outputFiles . find ( ( { path } ) => path . endsWith ( '.map' ) ) . text ; if ( options . minify ) { ( { code , map } = await minify ( code , map ) ) ; map = await massageSourcemaps ( map , options ) ; } await Promise . all ( [ fs . outputFile ( destFile , code ) , fs . outputFile ( ` ${ destFile } ` , map ) , ] ) ; await finishBundle ( destDir , destFilename , options , startTime ) ; } function remapDependenciesPlugin ( ) { const remaps = Object . entries ( options . remapDependencies ) . map ( ( [ path , value ] ) => ( { regex : new RegExp ( ` ${ path } ` ) , value } ) ) ; const external = options . externalDependencies ; return { name : 'remap-dependencies' , setup ( build ) { build . onResolve ( { filter : / .* / } , ( args ) => { const { path : importPath , resolveDir } = args ; const dep = importPath . startsWith ( '.' ) ? path . posix . join ( resolveDir , importPath ) : importPath ; for ( const { regex , value } of remaps ) { if ( ! regex . test ( dep ) ) { continue ; } const isExternal = external . includes ( value ) ; return { path : isExternal ? value : require . resolve ( value ) , external : isExternal , } ; } } ) ; } , } ; } await build ( startTime ) . catch ( ( err ) => handleBundleError ( err , ! ! options . watch , destFilename ) ) ; if ( options . watch ) { watchedTargets . set ( entryPoint , { rebuild : async ( ) => { const startTime = Date . now ( ) ; const buildPromise = build ( startTime ) . catch ( ( err ) => handleBundleError ( err , ! ! options . watch , destFilename ) ) ; if ( options . onWatchBuild ) { options . onWatchBuild ( buildPromise ) ; } await buildPromise ; } , } ) ; } }
Transforms a given JavaScript file entry point with esbuild and babel, and
 watches it for changes (if required).
Transforms a given JavaScript file entry point with esbuild and babel and watches it for changes ( if required ) .
/**
   * Splits up the wrapper to compute the banner and footer
   * @return {Object}
   */ /* enableCache */ /**
   * @param {number} startTime
   * @return {Promise<void>}
   */ // For es5 builds, ensure esbuild-injected code is transpiled. /**
   * Generates a plugin to remap the dependencies of a JS bundle.
   * @return {Object}
   */