Skip to content

Supports SourceMap on renderer and filter #5643

@wherewhere

Description

@wherewhere

Check List

  • I have already read Docs page.
  • I have already searched existing issues.

Feature Request

In renderer and filter we can only return the results of js and css. We can not create source map for it or get source map from prevent render or filter. It will be better if it can get and set source map in the pipeline. Such as:

hexo.extend.renderer.register("js", "js", data => {
  const sourceMap = data.sourceMap;
  const results = someCompiler(str, sourceMap);
  data.sourceMap = results.sourceMap;
  return results.code;
});
hexo.extend.filter.register("after_render:js", (str, data) => {
  const sourceMap = data.sourceMap;
  const results = someCompiler(str, sourceMap);
  data.sourceMap = results.sourceMap;
  return results.code;
});

Others

目前我只能通过 after_generateroute 里写入 SourceMap,这种方法想要获取之前的 SourceMap 会很麻烦,或许有更好的方法我并不知道,不过还是在编译期间传递 SourceMap 更方便。

/**
 * @this {import('@types/hexo')}
 */
function minifyJsWithMap() {
  const hexo = this
  const options = hexo.config.minify.js
  const { parse } = require('path')

  const route = hexo.route
  const routeList = route.list()
  /** @type {{ exclude: string[] }} */
  const { exclude, globOptions, verbose, ...babelOption } = options
  const include = ['*.js', ...exclude.map(x => `!${x}`)]

  delete babelOption.enable
  delete babelOption.priority

  return Promise.all((match(routeList, include, globOptions)).map(path => {
    return new Promise((/** @type {(value: void) => void} */ resolve, reject) => {
      const assetPath = route.get(path)
      let assetTxt = ''
      assetPath.on('data', chunk => (assetTxt += chunk))
      assetPath.on('end', async () => {
        if (assetTxt.length) {
          try {
            const { base, ext, name } = parse(path)
            const options = {
              ...babelOption,
              filename: path,
              sourceFileName: `${name}.source${ext}`
            }
            const results = await babelMinify(assetTxt, options)
            if (results) {
              const { code, map } = results
              if (verbose) logFn.call(this, assetTxt, code, path, 'js')
              if (babelOption.sourceMaps === true) {
                route.set(path, `${code}\n//# sourceMappingURL=${base}.map`)
              }
              else {
                route.set(path, code)
              }
              route.set(`${path}.map`, JSON.stringify(map))
            }
          } catch (err) {
            reject(new Error(`Path: ${path}\n${err}`))
          }
        }
        resolve()
      })
    })
  }))
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions