antd-mobile是蚂蚁金服出的挪动端设想指南和前端框架,它供应了一套基于React的挪动端组件库,能够很方便地用来开辟体验优越的挪动运用。
运用antd-mobile碰到的题目:react-native模块找不到
在阅读了antd-mobile的引见申明后,运用这一组件库好像很简朴,要做的只是装置和引入组件罢了:
装置
$ npm install antd-mobile --save
引入组件
import { Button } from 'antd-mobile/lib/button';
ReactDOM.render(<Button>按钮</Button>, mountNode);
antd-mobile的引见申明中引荐运用babel-plugin-import插件来按需加载类库,但为了削减早期运用antd-mobile所面对的复杂度,以上代码采用了最简朴的组件引入写法(显式指定组件的途径antd-mobile/lib/button
,并在HTML文件中零丁引入CSS款式文件antd-mobile/dist/antd-mobile.min.css
)。
在装置完antd-mobile模块并引入须要的组件后,接下来的一步就是构建全部挪动运用。此时,假如项目不是React Native运用,而是Web运用的话,构建历程会报错,显现react-native模块找不到(Error: Cannot resolve module 'react-native'...
)。这个毛病无疑是异常令人困惑的:当前所开辟的是一个一般的挪动端Web项目,与react-native没有任何关系,为什么须要react-native模块?事实上,纵然依据报错提醒装置react-native模块,在后续的构建历程当中也会报一些别的毛病,致使构建失利。
进一步的观察发明,题目出在antd-mobile的组件模块设想上。因为antd-mobile被设想为同时支撑React Native运用开辟和Web运用开辟,因而一切的组件都暴露为2个模块文件:index.js
和index.web.js
。个中,index.js
是给React Native开辟运用的,而index.web.js
则是给Web开辟运用的。因为Browserify和Webpack等打包东西在剖析JavaScript模块引入操纵时(require
或import
语句),会优先查找.js
后缀名的文件(当不指定模块文件名时,默许文件名即为index.js
),因而纵然当前项目与React Native无关,组件模块的引入操纵也会致使对react-native的依靠。
找到题目的缘由后,处理计划开端斟酌有2种:
引入模块时,显式指定模块文件的文件名(
import { Button } from 'antd-mobile/lib/button/index.web';
)。对Browserify或Webpack等打包东西举行设置,变动其模块引入操纵时的后缀名优先级,使得
.web.js
文件得以优先运用。
第一种计划比较简朴,对代码的改动量也很小。但事实证明,这一计划是行不通的:antd-mobile的组件代码中存在内部组件依靠(如List组件依靠ListItem组件,在List组件的index.web.js
文件中,会涌现require('./ListItem')
如许的代码),而这些引入内部组件的操纵并未指定详细的模块文件名,因而照样会发生require('./ListItem/index.js')
如许的结果,并终究致使对react-native的依靠。
关于第二种计划,假如是用Webpack打包,则antd-mobile社区有现成的处理方法 — 设定extensions
选项的值,并将.web.js
放在.js
之前即可。但在Browserify中,这一题目该怎样处理呢?
运用Browserify碰到的题目:怎样自定义模块文件后缀名的优先级?
和Webpack一样,Browserify也供应了一个叫extensions
的设置选项,用于设定模块文件的后缀名及其优先级。但和Webpack差别的是,Browserify中默许的2个模块文件后缀名(.js
和.json
)永久具有最高优先级,纵然在extensions
设置选项中设定.web.js
比.js
具有更高的优先级(extensions: ['.web.js', '.js', ...]
)也杯水车薪。缘由在于Browserify源代码中的以下这一行:
mopts.extensions = [ '.js', '.json' ].concat(mopts.extensions || []);
能够看到,不管设定的extensions
值为什么,.js
和.json
永久具有最高优先级。那末,在这类情况下怎样设定比.js
优先级还要高的模块文件后缀名呢?
在经由一些思考后,发明这个题目只能用比较hack的体式格局来处理:关于上述盘算终究extensions值的操纵,修正JavaScript中数组的concat
行动,让mopts.extensions
在[ '.js', '.json' ]
数组之前插进去,而不是在厥后增加。详细代码为:
var origin_concat = Array.prototype.concat;
Array.prototype.concat = function() {
if (this.length === 2 && this[0] === '.js' && this[1] === '.json') {
return origin_concat.apply(arguments[0], this);
}
return origin_concat.apply(this, arguments);
};
运转以上代码后,就能够经由过程设置extensions: ['.web.js', ...]
来用Browserify打包antd-mobile开辟的Web运用了。
模块笼统:browserify-high-priority-extensions
为了方便运用,上述hack Browserify的代码被笼统为一个模块:browserify-high-priority-extensions
,其意为”让Browserify的extensions选项值具有比默许的后缀名更高的优先级“。运用该模块异常简朴:
装置
$ npm install browserify-high-priority-extensions --save-dev
启用extensions高优先级设定
var hpe = require('browserify-high-priority-extensions');
hpe.enable();
启用后,即可经由过程设置extensions: ['.web.js', ...]
来用Browserify打包antd-mobile开辟的Web运用。
作废extensions高优先级设定
当不须要设置extensions
选项高优先级时,能够用以下语句恢复到默许状况:
hpe.disable();