js库打包兼容ie8浏览器踩坑(使用jquery1.9.1 + webpack5.91.0)

66 阅读2分钟
const path = require("path");

const webpack = require("webpack");

const UglifyJsPlugin = require("uglifyjs-webpack-plugin");

// 读取某一个文件里面的代码

const fs = require("fs");

const code = fs.readFileSync("./js/object-defineproperty-ie8.js", "utf8");

module.exports = {

mode: "production",

//入口路径

entry: {

bundle: "./index.js",

},

output: {

//出口路径

path: path.resolve(__dirname, "dist"),

filename: "bundle.js",

// 重新打包时, 先将之前打包的文件夹删除掉

clean: true,

// 下面是对es6代码转es5代码时保留哪些es6代码书写方式

environment: {

// The environment supports arrow functions ('() => { ... }').

arrowFunction: false,

// The environment supports const and let for variable declarations.

const: false,

// The environment supports BigInt as literal (123n).

bigIntLiteral: false,

// The environment supports destructuring ('{ a, b } = obj').

destructuring: false,

// The environment supports an async import() function to import EcmaScript modules.

dynamicImport: false,

// The environment supports 'for of' iteration ('for (const x of array) { ... }

forOf: false,

// The environment supports ECMAScript Module syntax to import ECMAScript modules (import ... from '...').

module: false,

// The environment supports optional chaining ('obj?.a' or 'obj?.()').

optionalChaining: true,

// The environment supports template literals.

templateLiteral: false,

},

},

target: "web",

// 使用loader加载器来处理规则

module: {

rules: [

{

test: /\.m?js$/,

exclude: /node_modules/,

use: [

{

loader: "babel-loader",

options: {

presets: [

[

"@babel/preset-env",

{

targets: {

ie: "8", // target for IE 8 ES3 for WebBrowser control

},

debug: true,

},

],

],

},

},

],

},

{

test: /\.(png|jpe?g|gif)$/i,

use: [

{

loader: "url-loader",

options: {

// 设置大小限制为80KB,小于这个大小的图片将被转换为Base64编码

limit: 81920,

},

},

],

},

{

// 基于正则匹配处理哪些文件

test: /\.(css)$/i,

// 控制使用哪个加载器loader(有顺序的:数组从右到左执行)

use: [

"style-loader", // 把编译好的css插入到页面的HEAD中(内嵌式样式)

"css-loader", // 编译@import/url()这种语法的

],

},

],

},

// 使用的jquery文件代码位置

resolve: {

alias: {

jquery: "./node_modules/jquery/jquery.js",

},

},

// 如果没有这个配置:打包后的代码会无法识别jquery的缩写:$、jquery、window.jquery

amd: {

jQuery: true,

},

plugins: [

// 将该代码插入到打包的文件头部,并且不会走打包转译的流程

new webpack.BannerPlugin({

banner: code,

raw: true,

entryOnly: true,

}),

// 将jquery全局插入使用

new webpack.ProvidePlugin({

$: "jquery",

jquery: "jquery",

"window.jquery": "jquery",

}),

],

// 对打包后的文件中的某一些关键字(比如class、for)使用引号来包裹防止报错

optimization: {

minimize: true,

minimizer: [

new UglifyJsPlugin({

uglifyOptions: {

ie8: true,

},

}),

],

},

};

ie8不支持的Object.defineProperty、bind函数:不要让这些代码走转译流程,转译之后可能会无法使用

// 让Object.defineProperty函数支持IE8

var origDefineProperty = Object.defineProperty;

var arePropertyDescriptorsSupported = function () {

var obj = {};

try {

origDefineProperty(obj, "x", { enumerable: false, value: obj });

for (var _ in obj) {

return false;

}

return obj.x === obj;

} catch (e) {

/* this is IE 8. */

return false;

}

};

var supportsDescriptors =

origDefineProperty && arePropertyDescriptorsSupported();

if (!supportsDescriptors) {

Object.defineProperty = function (a, b, c) {

//IE8支持修改元素节点的属性

if (origDefineProperty && a.nodeType == 1) {

return origDefineProperty(a, b, c);

} else {

a[b] = c.value || (c.get && c.get());

}

};

}

// 让bind函数支持IE8

if (!Function.prototype.bind) {

Function.prototype.bind = function (oThis) {

if (typeof this !== "function") {

throw new TypeError(

"Function.prototype.bind - what is trying to be bound is not callable"

);

}

var aArgs = Array.prototype.slice.call(arguments, 1),

fToBind = this,

fNOP = function () {},

fBound = function () {

return fToBind.apply(

this instanceof fNOP && oThis ? this : oThis,

aArgs.concat(Array.prototype.slice.call(arguments))

);

};

fNOP.prototype = this.prototype;

fBound.prototype = new fNOP();

return fBound;

};

}