微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Webpack无法调试`import ... from ...`变量;如何使webpack保持`import from`变量名

如何解决Webpack无法调试`import ... from ...`变量;如何使webpack保持`import from`变量名

例如,我的代码

import React from "react"

var node = <div></div>

当我在var node = <div></div>行的chrome devtools中设置断点时,它会引发错误

VM183:1 Uncaught ReferenceError: React is not defined

enter image description here

我知道原因是因为webpack从“ react”编译`import React,{createRef};遵循以下代码

var react_1 = __importStar(__webpack_require__(/*! react */ "./node_modules/react/index.js"));

但是我不知道如何预防

如何解决

解决方法

更新:

我发现以下问题:

https://github.com/webpack/webpack/issues/3957

最后,它提供了一个自定义的webpack插件,应该修复

https://gist.github.com/staeke/f197ff144e379aa884f91b95003f4ee1

完整代码在这里:

import {App} from "../src/App";

in webpack output become

var App_1 = __webpack_require__(/*! ../src/App */ "./src/App.tsx");

update:
the solution is make webpack plugin to hack webpack compiler(make webpack don't rename import from variable name)
https://gist.github.com/staeke/f197ff144e379aa884f91b95003f4ee1

the full webpack plugin code:

// This is a hack to just simplify variable namings,because they're ugly,for easier debugging
const HarmonyImportDependency = require('webpack/lib/dependencies/HarmonyImportDependency');
const HarmonyImportSpecifierDependency = require('webpack/lib/dependencies/HarmonyImportSpecifierDependency');
const HarmonyImportSpecifierDependencyTemplate = HarmonyImportSpecifierDependency.Template;
const path = require('path');

const HIDproto = HarmonyImportDependency.prototype;
const HISDTproto = HarmonyImportSpecifierDependencyTemplate.prototype;

const originalGetImportVar = HIDproto.getImportVar;
const originalGetImportStatement = HIDproto.getImportStatement;
const originalGetContent = HISDTproto.getContent;

const DEFAULT_MODULE_VAR_NAME_FN = str => {
  return '__' +  path.basename(str).replace(/[^a-zA-Z0-9$]+/g,'_');
}

module.exports = class SimplifyNamesPlugin {
  constructor(options) {
    this.options = options || {};
  }

  toIdentifier(str,scope) {
    if (!str || typeof str !== 'string') return str;

    let out = (this.options.moduleVarNameFn || DEFAULT_MODULE_VAR_NAME_FN)(str)

    const taken = scope.importVarMapVals || (scope.importVarMapVals = new Set());

    if (taken.has(out)) {
      let extra = '';
      while (taken.has(out + extra)) {
        const num = parseInt(extra.substr(1) || '0') + 1;
        extra = '_' + num;
      }
      out = out + extra;
    }

    taken.add(out);

    return out;
  }

  apply(compiler) {
    compiler.hooks.compilation.tap('HarmonyModulesPlugin',(compilation,{normalModuleFactory}) => {
      normalModuleFactory.hooks.parser
        .for('javascript/auto')
        .tap('HarmonyModulesPlugin',(parser,parserOptions) => {
          parser.hooks.importSpecifier.tap('HarmonyImportDependencyParserPlugin',(statement,source) => {
            const deps = parser.state.module.dependencies;
            deps[deps.length - 1].statement = statement;
          });
        });
    });


    if (HIDproto.getImportVar === originalGetImportVar) {
      const self = this;

      HIDproto.getImportVar = function() {
        let importVarMap = this.parserScope.importVarMap;
        if (!importVarMap) this.parserScope.importVarMap = importVarMap = new Map();
        let importVar = importVarMap.get(this.module);
        if (importVar) return importVar;
        importVar = self.toIdentifier(this.userRequest,this.parserScope);
        importVarMap.set(this.module,importVar);
        return importVar;
      }

      HIDproto.getImportStatement = function() {
        const orig = originalGetImportStatement.apply(this,arguments).replace('/* harmony import */ ','');
        const specifiers = this.statement &&  this.statement.specifiers;
        if (specifiers) {
          const importSpecifiers = specifiers.filter(s => s.type === 'ImportSpecifier');
          const importVars = importSpecifiers.map(s => {
            if (!s.imported)
              return null
            if (!s.local || s.local.name === s.imported.name)
              return s.imported.name;
            return s.imported.name + ':' + s.local.name
          }).filter(x => !!x)
          const defaultSpecifier = specifiers.find(s => s.type === 'ImportDefaultSpecifier');
          let last = ''
          const vals = [...this.parserScope.importVarMap.values()]
          const moduleName = [...vals][vals.length - 1]
          if (defaultSpecifier) {
            const name = defaultSpecifier.local.name
            importVars.push('default:' + name);
            last = `;if(typeof ${name}==="undefined")${name}=${moduleName}`
          }
          return `${orig.substr(0,orig.length - 1)}let {${importVars.join(',')}} = ${moduleName}${last};\n`;
        }
        return orig;
      };

      HISDTproto.getContent = function() {
        const orig = originalGetContent.apply(this,arguments);
        let out = orig;
        if (orig.startsWith('Object('))
          out = orig.substr(7,orig.length - 8);
        const match = out.match(/^(.+)\["([^\]]+)"]$/);
        if (match) {
          const legalId = match[2].match(/^[a-zA-Z][a-zA-Z0-9$]*$/);
          if (legalId) {
            out = match[1] + '.' + match[2];
          }
        }
        return out;
      };
    }
  }
};

旧:

我的tmp解决方案是,在使用打字稿时,使用const varName = require("path/to/lib")而不是import varName from "path/to/lib"

它将起作用

但是我仍然想从import from中找到一种支持debug var的方法(因为大多数代码样式​​是import from而不是const require

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。