用Browserify构建antd-mobile运用

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.jsindex.web.js。个中,index.js是给React Native开辟运用的,而index.web.js则是给Web开辟运用的。因为Browserify和Webpack等打包东西在剖析JavaScript模块引入操纵时(requireimport语句),会优先查找.js后缀名的文件(当不指定模块文件名时,默许文件名即为index.js),因而纵然当前项目与React Native无关,组件模块的引入操纵也会致使对react-native的依靠。

找到题目的缘由后,处理计划开端斟酌有2种:

  1. 引入模块时,显式指定模块文件的文件名(import { Button } from 'antd-mobile/lib/button/index.web'; )。

  2. 对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();
    原文作者:shaochuancs
    原文地址: https://segmentfault.com/a/1190000007334214
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞