尝试在Webpack中使用样式加载器时出现错误“未定义窗口”

时间:2020-05-20 22:03:09

标签: css angular webpack webpack-dev-server

我正在尝试使用Webpack Dev服务器来服务项目的前端。 我看到如果我使用样式加载器来处理css文件,则会收到此错误:

未定义窗口中的错误

我尝试通过以下检查来围绕窗口的引用来规避该问题:

if (typeof  window !== 'undefined') {

我必须为检查而修改的样式加载器库中整个“ addStyle.js”的内容粘贴在下面。

/*
    MIT License http://www.opensource.org/licenses/mit-license.php
    Author Tobias Koppers @sokra
*/

var stylesInDom = {};

var memoize = function (fn) {
    var memo;

    return function () {
        if (typeof memo === "undefined") memo = fn.apply(this, arguments);
        return memo;
    };
};

var isOldIE = memoize(function () {
    // Test for IE <= 9 as proposed by Browserhacks
    // @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
    // Tests for existence of standard globals is to allow style-loader
    // to operate correctly into non-standard environments
    // @see https://github.com/webpack-contrib/style-loader/issues/177
  if (typeof window !== 'undefined' && typeof  document !== 'undefined') {
    return window && document && document.all && !window.atob;
  }
});

var getTarget = function (target, parent) {
  if (parent){
    return parent.querySelector(target);
  }
  if (typeof  document !== 'undefined') {
    return document.querySelector(target);
  }
};

var getElement = (function (fn) {
    var memo = {};

    return function(target, parent) {
                // If passing function in options, then use it for resolve "head" element.
                // Useful for Shadow Root style i.e
                // {
                //   insertInto: function () { return document.querySelector("#foo").shadowRoot }
                // }
                if (typeof target === 'function') {
                        return target();
                }
                if (typeof memo[target] === "undefined") {
                  var styleTarget = getTarget.call(this, target, parent);
                  // Special case to return head of iframe instead of iframe itself
                  if (typeof window !== 'undefined') {
                    if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {
                      try {
                        // This will throw an exception if access to iframe is blocked
                        // due to cross-origin restrictions
                        styleTarget = styleTarget.contentDocument.head;
                      } catch (e) {
                        styleTarget = null;
                      }
                    }
                    memo[target] = styleTarget;
                  }
                }
        return memo[target]
    };
})();

var singleton = null;
var singletonCounter = 0;
var stylesInsertedAtTop = [];

var fixUrls = require("./urls");

module.exports = function(list, options) {
    if (typeof DEBUG !== "undefined" && DEBUG) {
        if (typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
    }

    options = options || {};

    options.attrs = typeof options.attrs === "object" ? options.attrs : {};

    // Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
    // tags it will allow on a page
    if (!options.singleton && typeof options.singleton !== "boolean") options.singleton = isOldIE();

    // By default, add <style> tags to the <head> element
        if (!options.insertInto) options.insertInto = "head";

    // By default, add <style> tags to the bottom of the target
    if (!options.insertAt) options.insertAt = "bottom";

    var styles = listToStyles(list, options);

    addStylesToDom(styles, options);

    return function update (newList) {
        var mayRemove = [];

        for (var i = 0; i < styles.length; i++) {
            var item = styles[i];
            var domStyle = stylesInDom[item.id];

            domStyle.refs--;
            mayRemove.push(domStyle);
        }

        if(newList) {
            var newStyles = listToStyles(newList, options);
            addStylesToDom(newStyles, options);
        }

        for (var i = 0; i < mayRemove.length; i++) {
            var domStyle = mayRemove[i];

            if(domStyle.refs === 0) {
                for (var j = 0; j < domStyle.parts.length; j++) domStyle.parts[j]();

                delete stylesInDom[domStyle.id];
            }
        }
    };
};

function addStylesToDom (styles, options) {
    for (var i = 0; i < styles.length; i++) {
        var item = styles[i];
        var domStyle = stylesInDom[item.id];

        if(domStyle) {
            domStyle.refs++;

            for(var j = 0; j < domStyle.parts.length; j++) {
                domStyle.parts[j](item.parts[j]);
            }

            for(; j < item.parts.length; j++) {
                domStyle.parts.push(addStyle(item.parts[j], options));
            }
        } else {
            var parts = [];

            for(var j = 0; j < item.parts.length; j++) {
                parts.push(addStyle(item.parts[j], options));
            }

            stylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};
        }
    }
}

function listToStyles (list, options) {
    var styles = [];
    var newStyles = {};

    for (var i = 0; i < list.length; i++) {
        var item = list[i];
        var id = options.base ? item[0] + options.base : item[0];
        var css = item[1];
        var media = item[2];
        var sourceMap = item[3];
        var part = {css: css, media: media, sourceMap: sourceMap};

        if(!newStyles[id]) styles.push(newStyles[id] = {id: id, parts: [part]});
        else newStyles[id].parts.push(part);
    }

    return styles;
}

function insertStyleElement (options, style) {
    var target = getElement(options.insertInto)

    if (!target) {
        throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.");
    }

    var lastStyleElementInsertedAtTop = stylesInsertedAtTop[stylesInsertedAtTop.length - 1];

    if (options.insertAt === "top") {
        if (!lastStyleElementInsertedAtTop) {
            target.insertBefore(style, target.firstChild);
        } else if (lastStyleElementInsertedAtTop.nextSibling) {
            target.insertBefore(style, lastStyleElementInsertedAtTop.nextSibling);
        } else {
            target.appendChild(style);
        }
        stylesInsertedAtTop.push(style);
    } else if (options.insertAt === "bottom") {
        target.appendChild(style);
    } else if (typeof options.insertAt === "object" && options.insertAt.before) {
        var nextSibling = getElement(options.insertAt.before, target);
        target.insertBefore(style, nextSibling);
    } else {
        throw new Error("[Style Loader]\n\n Invalid value for parameter 'insertAt' ('options.insertAt') found.\n Must be 'top', 'bottom', or Object.\n (https://github.com/webpack-contrib/style-loader#insertat)\n");
    }
}

function removeStyleElement (style) {
    if (style.parentNode === null) return false;
    style.parentNode.removeChild(style);

    var idx = stylesInsertedAtTop.indexOf(style);
    if(idx >= 0) {
        stylesInsertedAtTop.splice(idx, 1);
    }
}

function createStyleElement (options) {
  if (typeof  document !== 'undefined') {
    var style = document.createElement("style");

    if (options.attrs.type === undefined) {
      options.attrs.type = "text/css";
    }

    if (options.attrs.nonce === undefined) {
      var nonce = getNonce();
      if (nonce) {
        options.attrs.nonce = nonce;
      }
    }

    addAttrs(style, options.attrs);
    insertStyleElement(options, style);

    return style;
  }
}

function createLinkElement (options) {
  if (typeof  document !== 'undefined') {
    var link = document.createElement("link");

    if (options.attrs.type === undefined) {
      options.attrs.type = "text/css";
    }
    options.attrs.rel = "stylesheet";

    addAttrs(link, options.attrs);
    insertStyleElement(options, link);

    return link;
  }
}

function addAttrs (el, attrs) {
    Object.keys(attrs).forEach(function (key) {
        el.setAttribute(key, attrs[key]);
    });
}

function getNonce() {
    if (typeof __webpack_nonce__ === 'undefined') {
        return null;
    }

    return __webpack_nonce__;
}

function addStyle (obj, options) {
    var style, update, remove, result;

    // If a transform function was defined, run it on the css
    if (options.transform && obj.css) {
        result = typeof options.transform === 'function'
         ? options.transform(obj.css)
         : options.transform.default(obj.css);

        if (result) {
            // If transform returns a value, use that instead of the original css.
            // This allows running runtime transformations on the css.
            obj.css = result;
        } else {
            // If the transform function returns a falsy value, don't add this css.
            // This allows conditional loading of css
            return function() {
                // noop
            };
        }
    }

    if (options.singleton) {
        var styleIndex = singletonCounter++;

        style = singleton || (singleton = createStyleElement(options));

        update = applyToSingletonTag.bind(null, style, styleIndex, false);
        remove = applyToSingletonTag.bind(null, style, styleIndex, true);

    } else if (
        obj.sourceMap &&
        typeof URL === "function" &&
        typeof URL.createObjectURL === "function" &&
        typeof URL.revokeObjectURL === "function" &&
        typeof Blob === "function" &&
        typeof btoa === "function"
    ) {
        style = createLinkElement(options);
        update = updateLink.bind(null, style, options);
        remove = function () {
            removeStyleElement(style);

            if(style.href) URL.revokeObjectURL(style.href);
        };
    } else {
        style = createStyleElement(options);
        update = applyToTag.bind(null, style);
        remove = function () {
            removeStyleElement(style);
        };
    }

    update(obj);

    return function updateStyle (newObj) {
        if (newObj) {
            if (
                newObj.css === obj.css &&
                newObj.media === obj.media &&
                newObj.sourceMap === obj.sourceMap
            ) {
                return;
            }

            update(obj = newObj);
        } else {
            remove();
        }
    };
}

var replaceText = (function () {
    var textStore = [];

    return function (index, replacement) {
        textStore[index] = replacement;

        return textStore.filter(Boolean).join('\n');
    };
})();

function applyToSingletonTag (style, index, remove, obj) {

  if (!style) {
    return
  }
    var css = remove ? "" : obj.css;

    if (style.styleSheet) {
        style.styleSheet.cssText = replaceText(index, css);
    } else {
    if (typeof  document !== 'undefined') {
      var cssNode = document.createTextNode(css);
      var childNodes = style.childNodes;

      if (childNodes[index]) style.removeChild(childNodes[index]);

      if (childNodes.length) {
        style.insertBefore(cssNode, childNodes[index]);
      } else {
        style.appendChild(cssNode);
      }
    }
    }
}

function applyToTag (style, obj) {
  if (!style) {
    return
  }
    var css = obj.css;
    var media = obj.media;

    if(media) {
        style.setAttribute("media", media)
    }

    if(style.styleSheet) {
        style.styleSheet.cssText = css;
    } else {
        while(style.firstChild) {
            style.removeChild(style.firstChild);
        }
    if (typeof  document !== 'undefined') {
      style.appendChild(document.createTextNode(css));
    }
    }
}

function updateLink (link, options, obj) {
    var css = obj.css;
    var sourceMap = obj.sourceMap;

    /*
        If convertToAbsoluteUrls isn't defined, but sourcemaps are enabled
        and there is no publicPath defined then lets turn convertToAbsoluteUrls
        on by default.  Otherwise default to the convertToAbsoluteUrls option
        directly
    */
    var autoFixUrls = options.convertToAbsoluteUrls === undefined && sourceMap;

    if (options.convertToAbsoluteUrls || autoFixUrls) {
        css = fixUrls(css);
    }

    if (sourceMap) {
        // http://stackoverflow.com/a/26603875
        css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + " */";
    }

    var blob = new Blob([css], { type: "text/css" });

    var oldSrc = link.href;

    link.href = URL.createObjectURL(blob);

    if(oldSrc) URL.revokeObjectURL(oldSrc);
}

但是现在我收到另一个错误,提示app.css文件未返回任何字符串。

尽管仍然使用样式加载器来提供前端服务(即未定义Window错误不会阻止Webpack提供内容),但它禁用了热部署,这是我尝试实现此功能的主要原因。

感谢您的阅读!任何帮助,将不胜感激。

0 个答案:

没有答案