esbuild#Loader TypeScript Examples

The following examples show how to use esbuild#Loader. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: EsbuildPlugin.ts    From web with MIT License 6 votes vote down vote up
async transform(context: Context) {
    let loader: Loader;

    if (context.response.is('html')) {
      // we are transforming inline scripts
      loader = 'js';
    } else {
      const fileExtension = path.posix.extname(context.path);
      loader = this.esbuildConfig.loaders[fileExtension];
    }

    if (!loader) {
      // we are not handling this file
      return;
    }

    const target = getEsbuildTarget(this.esbuildConfig.target, context.headers['user-agent']);
    if (target === 'esnext' && loader === 'js') {
      // no need run esbuild, this happens when compile target is set to auto and the user is on a modern browser
      return;
    }

    const filePath = getRequestFilePath(context.url, this.config!.rootDir);
    if (context.response.is('html')) {
      this.transformedHtmlFiles.push(context.path);
      return this.__transformHtml(context, filePath, loader, target);
    }

    return this.__transformCode(context.body as string, filePath, loader, target);
  }
Example #2
Source File: EsbuildPlugin.ts    From web with MIT License 6 votes vote down vote up
private async __transformHtml(
    context: Context,
    filePath: string,
    loader: Loader,
    target: string | string[],
  ) {
    const documentAst = parseHtml(context.body as string);
    const inlineScripts = queryAll(
      documentAst,
      predicates.AND(
        predicates.hasTagName('script'),
        predicates.NOT(predicates.hasAttr('src')),
        predicates.OR(
          predicates.NOT(predicates.hasAttr('type')),
          predicates.hasAttrValue('type', 'module'),
        ),
      ),
    );

    if (inlineScripts.length === 0) {
      return;
    }

    for (const node of inlineScripts) {
      const code = getTextContent(node);
      const transformedCode = await this.__transformCode(code, filePath, loader, target);
      setTextContent(node, transformedCode);
    }

    return serializeHtml(documentAst);
  }
Example #3
Source File: EsbuildPlugin.ts    From web with MIT License 5 votes vote down vote up
private async __transformCode(
    code: string,
    filePath: string,
    loader: Loader,
    target: string | string[],
  ): Promise<string> {
    try {
      const transformOptions: TransformOptions = {
        sourcefile: filePath,
        sourcemap: 'inline',
        loader,
        target,
        // don't set any format for JS-like formats, otherwise esbuild reformats the code unnecessarily
        format: ['js', 'jsx', 'ts', 'tsx'].includes(loader) ? undefined : 'esm',
        jsxFactory: this.esbuildConfig.jsxFactory,
        jsxFragment: this.esbuildConfig.jsxFragment,
        define: this.esbuildConfig.define,
        tsconfigRaw: this.tsconfigRaw,
      };

      const { code: transformedCode, warnings } = await transform(code, transformOptions);

      if (warnings) {
        const relativePath = path.relative(process.cwd(), filePath);

        for (const warning of warnings) {
          if (!filteredWarnings.some(w => warning.text.includes(w))) {
            this.logger!.warn(
              `[@web/test-runner-esbuild] Warning while transforming ${relativePath}: ${warning.text}`,
            );
          }
        }
      }

      return transformedCode;
    } catch (e) {
      if (Array.isArray(e.errors)) {
        const msg = e.errors[0] as Message;

        if (msg.location) {
          throw new PluginSyntaxError(
            msg.text,
            filePath,
            code,
            msg.location.line,
            msg.location.column,
          );
        }

        throw new Error(msg.text);
      }

      throw e;
    }
  }
Example #4
Source File: esbuildPluginFactory.ts    From web with MIT License 5 votes vote down vote up
export function esbuildPlugin(args: EsBuildPluginArgs = {}): Plugin {
  const target = args.target ?? 'auto';
  const loaders: Record<string, Loader> = {};
  for (const [key, value] of Object.entries(args.loaders ?? {})) {
    loaders[key.startsWith('.') ? key : `.${key}`] = value;
  }
  if (args.ts) {
    loaders['.ts'] = 'ts';
  }
  if (args.jsx) {
    loaders['.jsx'] = 'jsx';
  }
  if (args.tsx) {
    loaders['.tsx'] = 'tsx';
  }
  if (args.json) {
    loaders['.json'] = 'json';
  }
  if (args.js) {
    loaders['.js'] = 'js';
  }
  if (
    !Object.prototype.hasOwnProperty.call(loaders, '.js') &&
    (typeof args.target === 'string' || Array.isArray(args.target))
  ) {
    loaders['.js'] = 'js';
  }

  const handledExtensions = Object.keys(loaders);
  const tsFileExtensions: string[] = [];
  for (const [extension, loader] of Object.entries(loaders)) {
    if (loader === 'ts' || loader === 'tsx') {
      tsFileExtensions.push(extension);
    }
  }

  return new EsbuildPlugin({
    loaders,
    target,
    handledExtensions,
    tsFileExtensions,
    jsxFactory: args.jsxFactory,
    jsxFragment: args.jsxFragment,
    define: args.define,
    tsconfig: args.tsconfig,
  });
}
Example #5
Source File: transformJS.ts    From toy-vite with MIT License 5 votes vote down vote up
export function transformCode(opts: { code: string; loader?: Loader }) {
  return transformSync(opts.code, {
    loader: opts.loader || 'ts',
    sourcemap: true,
    format: 'esm',
  });
}
Example #6
Source File: transformJS.ts    From toy-vite with MIT License 5 votes vote down vote up
export function transformJS(opts: {
  appRoot: string;
  path: string;
  code: string;
}): TransformResult {
  const ext = extname(opts.path).slice(1);
  const ret = transformCode({
    code: opts.code,
    loader: ext as Loader,
  });

  let { code } = ret;
  code = code.replace(
    /\bimport(?!\s+type)(?:[\w*{}\n\r\t, ]+from\s*)?\s*("([^"]+)"|('[^']+'))/gm,
    (a, b, c) => {
      let from: string;
      if (c.charAt(0) === '.') {
        from = join(dirname(opts.path), c);
        const filePath = join(opts.appRoot, from);
        if (!existsSync(filePath)) {
          if (existsSync(`${filePath}.tsx`)) {
            from = `${from}.tsx`;
          } else if (existsSync(`${filePath}.ts`)) {
            from = `${from}.ts`;
          }
        }
        if (['svg'].includes(extname(from).slice(1))) {
          from = `${from}?import`;
        }
      } else {
        from = `/src/.cache/${c}.js`;
      }

      // TODO: support cjs
      // if (c === 'react') {
      //   a = 'import cjsImport0_react from "react"; ';
      //   // a = a.replace()
      // }

      return a.replace(b, `"${from}"`);
    },
  );

  return {
    ...ret,
    code,
  };
}
Example #7
Source File: cli.ts    From nota with MIT License 4 votes vote down vote up
cli = (
  externalOptions?: CliOptions
): ((extra: BuildOptions) => Promise<[BuildResult, BuildOptions]>) => {
  let options =
    externalOptions ||
    (program
      .option("-w, --watch", "Watch for changes and rebuild")
      .option("-g, --debug", "Do not minify and include source maps")
      .option("-t, --typescript", "Run typescript")
      .parse(process.argv)
      .opts() as CliOptions);

  let pkg = getManifest();
  let keys = (map?: IDependencyMap) => Object.keys(map || {});
  let pkgExternal = keys(pkg.dependencies).concat(keys(pkg.peerDependencies));

  return async (extra: BuildOptions = {}) => {
    let plugins = extra.plugins || [];
    let format = extra.format || "esm";

    let external = (format != "iife" ? pkgExternal : []).concat(extra.external || []);

    if (format == "esm") {
      plugins.push(esmExternalsPlugin({ externals: external }));
    }

    let loader: { [ext: string]: Loader } = {
      ".otf": "file",
      ".woff": "file",
      ".woff2": "file",
      ".ttf": "file",
      ".wasm": "file",
      ".bib": "text",
      ".png": "file",
      ".jpg": "file",
      ".jpeg": "file",
      ".gif": "file",
      ...(extra.loader || {}),
    };

    let outpaths: BuildOptions = {};
    if (extra.outdir) {
      outpaths.outdir = extra.outdir;
    } else if (extra.outfile) {
      outpaths.outfile = extra.outfile;
    } else {
      extra.outdir = "dist";
    }

    let debug = options.debug || options.watch !== undefined;
    let watch: WatchMode | undefined =
      typeof options.watch === "object"
        ? options.watch
        : options.watch
        ? {
            onRebuild() {
              log.info("Rebuilt.");
            },
          }
        : undefined;

    let entryPoints = extra.entryPoints;
    if (!entryPoints) {
      entryPoints = [(await fileExists("./lib/index.ts")) ? "./lib/index.ts" : "./lib/index.tsx"];
    }

    if (options.ts || _.some(entryPoints, (p: string) => path.extname(p).startsWith(".ts"))) {
      plugins.push(tscPlugin());
    }

    let opts = {
      ...extra,
      ...outpaths,
      entryPoints,
      watch,
      external,
      plugins,
      format,
      loader,
      bundle: extra.bundle !== undefined ? extra.bundle : true,
      minify: extra.minify !== undefined ? extra.minify : !debug,
      sourcemap: extra.sourcemap !== undefined ? extra.sourcemap : debug,
    };

    let start = _.now();
    let result = await esbuild.build(opts);
    log.info(`Built in ${((_.now() - start) / 1000).toFixed(2)}s.`);
    return [result, opts];
  };
}