使用 webpack 项目按需引入打包

前言

现在项目打包,打多数是用的 webpack 来打包的。可能处于某种原因,例如带宽呀,节约服务器资源呀等,以及访问性能呀,会要求我们按需打包,打包后的文件尽可能的小,且兼容一些低版本的浏览器。

那如何按需引入,又该如何按需打包呢?今天我们就一起来探讨一下!

言归正传

接下来,我们会做些测试,来一步一步说明,如何按需引用和打包的。
我们先写一段 ES6 语法的测试代码,如下:

src/index.js 文件

const fn = ()=>{
    console.log('this is fn()')
}
fn();
new Promise(()=>{})
Array.from(new Set([1,2,3,4]))
class A { }

运行 npm run serve 命令,启动后点击 F12 选择 Sources 选项查看我们的打包文件,如下:

image.png

可以看到,我们写的 ES6 语法,并没有转换成 ES5 语法?

有同学可能会说,还没引入 babel
是没引入,那为何引入 babel 就可以了,babel 又偷摸做了什么事呢?

说到 babel 不得不提 预设包 @babel/preset-env,这包说明了 babel 本身不能把 ES6 转换成 ES5 的,它只是提供了一个平台,这个平台是依赖 babel core 来实现的。那 babel core 就是干活的吗?答案是否定的,它只是相当于一个组织者,组织了各种语法对应的的插件。

简单讲就是:预设包就是许多 babel 插件的集合包,用来解析多个ES6 的语法。

预设包 也不是万能的,它只能转换浏览器不兼容的语法,比如 const、let、class 以及 箭箭头函数 等,不能转换新的的 API , 例如 Peomise、Set、Map 以及 Object.assign() 等。

怎么办呢?这时又来了一个包 @babel/polyfill 又称 补丁包。它包含了两个插件
core-js: 实现了除 async await 外所有 ES6、ES7、以及 ES8 语法
regenerator-runtime:实现了 async await

我们接下来最为关键的异步,配置 babel

  1. 安装 babel 相关包
npm install -D babel-loader @babel/core @babel/preset-env
  1. webpack.config.js 文件里配置 rules
module:{
        rules:[
            // 处理 ES6 => ES5 
            {
                test: /\.js/, // 需要处理的文件类型
                include: [resolve('src')], // 需要梳理的文件
                // 组合一 use 后面跟字符串
                use: 'babel-loader',
                // 组合二 use 后面是数组,每项元素是对象,可单独配置 或者 数组每项是字符串,相当于组合一
                // use: [
                //     {
                //         laoder: 'babel-loader',
                //         options: {
                //             presets: [],
                //             plugins: []
                //         },
                //     }
                // ],
                // use: ['babel-loader'],
                // 组合三 loader + options
                // loader: 'babel-loader',
                // options: {
                //     presets: [],
                //     plugins: []
                // }
            }
        ]
    }
  1. 创建 babel.config.js 文件并配置
module.exports = function(api) {
    api.cache(true); // 缓存加快打包

    // 每个预设 都是一个数组,包含 第一项是名称,第二项是配置
    // const presets = [
    //     [
    //         '@babel/preset-env',
    //         {
    //             // 如需要配置项
    //         }
    //     ],
    //     [
    //          // 其他配置项
    //     ]
    // ]

    // 如果不需要配置,可简写
    const presets = ['@babel/preset-env'];
    const plugins = [];

    return {
        presets, plugins
    }
}
  1. 再次运行 npm run serve 命令,启动后点击 F12 选择 Sources 选项查看我们的打包文件,如下:
image.png

由上可以看出,ES6 语法已经被转换为 ES5 的语法了。

但有一个问题没有解决:生成的文件里有 Promise ,这就意味着低版本浏览器不支持,可能导致我们的项目没法正常运行。

这是可以用到我们提到过的一个包 @babel/polyfill

安装
npm install @babel/polyfill -D

在程序头部引入
import '@babel/polyfill’

配置好后, npm run serve 命令,启动后点击 F12 选择 Sources 选项查看我们的打包文件已经多出了 Promise 及相关的定义。

这时问题又来了,引入 @babel/polyfill 后打包的文件体积变大了,也就是说,不管你当前的浏览器支不支持 Promise 它都会重新定义, 从而造成了资源浪费。
而我们想要的结果是:
浏览器不支持我们就引入 @babel/polyfill,否则不引入。

解决这个问题只需在 babel.config.js 中配置 useBuiltlns,且有三种方案,不需要在程序文件中单独引入,具体如下:

  1. 配置 为 useBuiltlns: false
const presets = [
    [  '@babel/preset-env' ]
]

等同于

const presets = [
    [  
        '@babel/preset-env',
        {
             "useBuiltlns": "false"
        }
    ]
]

特点:

  • 不管项目中用没用到 ES6/7/8 它都会全部引入所有浏览器的兼容
  1. 配置 为 useBuiltlns: entry
const presets = [
    [
        '@babel/preset-env',
        {
            "useBuiltlns": "entry", // 默认是 false 即全部打包
             "corejs": 2,
            "targets": { //指定浏览器兼容的最低版本
                "edge": 70,
                // "ie": 10,
                "chrome": 67
            } 
        }
    ]
]

特点:

  • 会全部引入从设置的最低版本起的所有 ES6/7/8的语法
  • 兼容浏览器版本越低,打包的文件体积越大。
  1. 配置 为 useBuiltlns: usage
const presets = [
    [
        '@babel/preset-env',
        {
            "useBuiltlns": "usage", // 默认是 false 即全部打包
             "corejs": 2,
            "targets": { //指定浏览器兼容的最低版本
                "edge": 70,
                // "ie": 10,
                "chrome": 67
            } 
        }
    ]
]

特点:

  • 只会引入项目所需的 ES6/7/8 的语法

文档到此咱们的研究就告一段落了,实现了项目文件按需引入并打包。
赶紧试试吧,记得点赞转发哦 ~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,923评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,154评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,775评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,960评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,976评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,972评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,893评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,709评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,159评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,400评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,552评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,265评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,876评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,528评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,701评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,552评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,451评论 2 352

推荐阅读更多精彩内容