详解webpack import()动态加载模块踩坑


Posted in Javascript onJuly 17, 2018

import

webpack根据ES2015 loader 规范实现了用于动态加载的import()方法。

这个功能可以实现按需加载我们的代码,并且使用了promise式的回调,获取加载的包。

在代码中所有被import()的模块,都将打成一个单独的包,放在chunk存储的目录下。在浏览器运行到这一行代码时,就会自动请求这个资源,实现异步加载。

这里是一个简单的demo。

import('lodash').then(_ => {
  // Do something with lodash (a.k.a '_')...
 })

可以看到,import()的语法十分简单。该函数只接受一个参数,就是引用包的地址,这个地址与es6的import以及CommonJS的require语法用到的地址完全一致。可以实现无缝切换【写个正则替换美滋滋】。

并且使用了Promise的封装,开发起来感觉十分自在。【包装一个async函数就更爽了】

然而,以上只是表象。

只是表象。

我在开发的时候就遇到了问题。场景是这样的:一个对象,存储的是各级的路由信息,及其对应的页面组件。为减少主包大小,我们希望动态加载这些页面。

同时使用了react-loadable来简化组件的懒加载封装。代码如下所示。

function lazyLoad(path) {
 return Loadable({
  loader: () => import(path),
  loading: Spin,
 });
}

然后我就开始开心的在代码中写上lazyLoad('./pages/xxx')。果不其然,挂了。浏览器表示,没有鱼丸没有粗面,也不知道这个傻逼模块在哪里。

于是我查看了官方文档,发现有一个黄条提示。

详解webpack import()动态加载模块踩坑

emmm,看来问题出在这里了。

这个现象其实是与webpack import()的实现高度相关的。由于webpack需要将所有import()的模块都进行单独打包,所以在工程打包阶段,webpack会进行依赖收集。

此时,webpack会找到所有import()的调用,将传入的参数处理成一个正则,如:

import('./app'+path+'/util') => /^\.\/app.*\/util$/

也就是说,import参数中的所有变量,都会被替换为【.*】,而webpack就根据这个正则,查找所有符合条件的包,将其作为package进行打包。

详解webpack import()动态加载模块踩坑

因此,如果我们直接传入一个变量,webpack就会把 (整个电脑的包都打包进来[不闹]) 认为你在逗他,并且抛出一个WARNING: Critical dependency: the request of a dependency is an expression。

所以import的正确姿势,应该是尽可能静态化表达包所处的路径,最小化变量控制的区域

如我们要引用一堆页面组件,可以使用import('./pages/'+ComponentName),这样就可以实现引用的封装,同时也避免打包多余的内容。

另外一个影响功能封装的点,是import()中的相对路径,是import语句所在文件的相对路径,所以进一步封装import时会出现一些麻烦。

因为import语句中的路径会在编译后被处理成webpack命令执行目录的相对路径.

友情链接:https://webpack.js.org/api/module-methods/#import

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript验证身份证号
Mar 03 Javascript
javascript实现在线客服效果
Jul 15 Javascript
JavaScript动态改变div属性的实现方法
Jul 22 Javascript
JavaScript数组的一些奇葩行为
Jan 25 Javascript
浅谈javascript运算符——条件,逗号,赋值,()和void运算符
Jul 15 Javascript
AngularJS ng-repeat指令中使用track by子语句解决重复数据遍历错误问题
Jan 21 Javascript
vue cli升级webapck4总结
Apr 04 Javascript
es6新特性之 class 基本用法解析
May 05 Javascript
vue-image-crop基于Vue的移动端图片裁剪组件示例
Aug 28 Javascript
微信小程序textarea层级过高的解决方法
Mar 04 Javascript
vue cli使用融云实现聊天功能的实例代码
Apr 19 Javascript
Vue实现附件上传功能
May 28 Javascript
vue-router中的hash和history两种模式的区别
Jul 17 #Javascript
JS使用tween.js动画库实现轮播图并且有切换功能
Jul 17 #Javascript
SVG实现时钟效果
Jul 17 #Javascript
JS中实现隐藏部分姓名或者电话号码的代码
Jul 17 #Javascript
基于D3.js实现时钟效果
Jul 17 #Javascript
vue生成token并保存到本地存储中
Jul 17 #Javascript
vue脚手架搭建项目的兼容性配置详解
Jul 17 #Javascript
You might like
在php中判断一个请求是ajax请求还是普通请求的方法
2011/06/28 PHP
Linux系统递归生成目录中文件的md5的方法
2015/06/29 PHP
php数组函数array_walk用法示例
2016/05/26 PHP
PHP实现随机生成水印图片功能
2017/03/22 PHP
yii2.0框架使用 beforeAction 防非法登陆的方法分析
2019/09/11 PHP
laravel model 两表联查示例
2019/10/24 PHP
jQuery 性能优化指南 (1)
2009/05/21 Javascript
JS模拟面向对象全解(一、类型及传递)
2011/07/13 Javascript
Javascript继承机制的设计思想分享
2011/08/28 Javascript
判断ie的两种简单方法
2013/08/12 Javascript
JS检测输入字符是否包含非法字符的示例代码
2014/02/11 Javascript
jQuery操作JSON的CRUD用法实例
2015/02/25 Javascript
JavaScript中的this机制
2016/01/30 Javascript
BootStrap的select2既可以查询又可以输入的实现代码
2017/02/17 Javascript
Angularjs使用指令做表单校验的方法
2017/03/31 Javascript
深入理解angular2启动项目步骤
2017/07/15 Javascript
laydate 显示结束时间不小于开始时间的实例
2017/08/11 Javascript
Vue组件和Route的生命周期实例详解
2018/02/10 Javascript
详解angular2 控制视图的封装模式
2018/12/27 Javascript
vue项目中使用rem,在入口文件添加内容操作
2020/11/11 Javascript
Python中工作日类库Busines Holiday的介绍与使用
2017/07/06 Python
详解利用django中间件django.middleware.csrf.CsrfViewMiddleware防止csrf攻击
2018/10/09 Python
Python如何处理大数据?3个技巧效率提升攻略(推荐)
2019/04/15 Python
Django 路由控制的实现
2019/07/17 Python
Django发送邮件和itsdangerous模块的配合使用解析
2019/08/10 Python
Python爬虫 urllib2的使用方法详解
2019/09/23 Python
python音频处理的示例详解
2020/12/23 Python
使用 HTML5 Canvas 制作水波纹效果点击图片就会触发
2014/09/15 HTML / CSS
.NET面试题:什么是反射
2016/09/30 面试题
40岁生日感言
2014/02/15 职场文书
音乐幼师求职信
2014/07/09 职场文书
迎新生欢迎词
2015/01/23 职场文书
爱牙日宣传活动总结
2015/02/05 职场文书
门店店长岗位职责
2015/04/14 职场文书
小学新课改心得体会
2016/01/22 职场文书
幼儿园语言教学反思
2016/02/23 职场文书