如何发布一个 React components

本文讲的是如何发布一个 React components,


在我开源 react-place 项目到时候,我注意到那么一个问题。那就是,准备构件发布有些复杂。因此,我决定在此记录该过程,以便日后遇到同样的问题时可查。

在准备构件期间,你会惊奇地发现建立jsx文件并不意味着该构件可用于发布,或该构件对于其他开发人员来说是可用的东西。

构件

react-place 是一个提供输入服务的构件。当用户输入一个城市的名字时,该构件会作出预测并提供建议选项给该用户。onLocationSet是该构件的一个属性。当用户选择某些建议选项时,它将会被触发。触发后,构件里的一个函数,它将接收一个对象作为参数输入。该对象包含有对一个城市的简短描述以及其地理坐标。总的来说,我们是和一个外部 API (谷歌地图)和一个参与的硬关联(自动完成输入组件)进行通信操作。这里有一个例子,它将展示该构件如何工作。

下面,我们来一起看看构件是如何完成?为何完成后,该构件还不能被发布?

时下,有一些概念处于风口浪尖。其中,就有 React 和它的 JSX 语法。另外,还有新版的 ES6 标准,而所有的这些,都与我们的浏览器息息相关。虽然,我想尽早应用这些新鲜的概念,但我需要一个转译器,用于解决它们兼容性不高的问题。该转译器将需要解析 ES6 标准下的代码并生成对应 ES5 标准下的。Babel 就是一款专门做这样工作的转换编译器,并且它能很好地结合于 React 使用。除了转译器之外,我还需要一个代码包装工具。该工具能解析输入并生成一个包含应用的文件。在众多包装工具中,webpack 是我的选择。

主要开发过程

两周前,我创建了一个 react-webpack-started。它接收一个 JSX 文件作为输入并用 Babel 生成对应的 ES5 文件。我们有一部本地开发伺服器、测试设定以及一个 linter 插件,然而这是另外一个故事,这里并不详述。(在这里有相关更多的信息)。

在半年前,我更喜欢用 NPM 来定义项目的任务建立。下面是我刚开始可以运行的 NPM 脚本:

// in package.json
"scripts": {
  "dev": "./node_modules/.bin/webpack --watch --inline",
  "test": "karma start",
  "test:ci": "watch 'npm run test' src/"
}

npm run dev 该命令将触发 webpack 进行编译并启动设备进行服务。测试是通过 Karma runner 和 Phantomjs 来完成的。而我使用的文件结构则如下所示:

|
+-- example-es6
|   +-- build
|   |   +-- app.js
|   |   +-- app.js.map
|   +-- src
|   |   +-- index.js
|   +-- index.html
+-- src
    +-- vendor
    |   +-- google.js
    + -- Location.jsx

我要发布的构件是放在Location.jsx里。为了测试它,我创建了一个简单的 app 应用(example-es6 文件夹)来导入该文件。

花了一些时间,终于把该构件开发完成。我把更改部分推送到 GitHub 的 repository 并错误认为该构件已经可以被分享出去。然而,五分钟后我意识到这构件并不能。那是因为:

  • 如果我以 NPM 包发布该构件,我将需要一个入口地址。那么我想,我的 JSX 文件适合作入口地址吗?并不能,因为并不是所有的开发人员都喜欢 JSX。因此,该构件应该开发成非 JSX 版本。
  • 我入口地址的代码是遵循 ES6 标准来书写的,然而并不是所有的开发者都遵循 ES6 标准且在建立过程中使用到转译器。因此,入口地址代码应该是遵循兼容性更高的 ES5 标准。
  • webpack 的输出确实满足了上面所述的两个要求,然而它有一个问题。那就是该代码包装工具包含了整个 React 库,而我们想包装的只是该组件,不是 React。

综上所述,webpack 在开发过程的确是很有用,然而却并不能生成一个可用于引入或导入的文件。我尝试过使用 webpack 的externals 选项来解决问题。但是我发现,当我们有全局可用的依赖时,该问题仍然是存在的。

建立符合 ES5 标准的入口地址

从前面可以看到,定义一个是新的 NPM 脚本是很重要的。 NPM 甚至一个prepublish入口。它可以在包发布前且在本地执行npm install命令时运行。下面是我新添加的定义:

// package.json
"scripts": {
  "prepublish": "./node_modules/.bin/babel ./src --out-dir ./lib --source-maps --presets es2015,react"
  ...
}

在这里,我们不需要使用 webpack,而只是使用 Babel。它会从src文件夹获取所有需要的东西,转化 JSX 文件为纯 JavaScript 调用并把 ES6 标准下的代码转成 ES5标准下的。 因此,文件结构将是:

|
+-- example-es6
+-- lib
|   +-- vendor
|   |   +-- google.js
|   |   +-- google.js.map
|   +-- Location.js
|   +-- Location.js.map
+-- src
    +-- vendor
    |   +-- google.js
    + -- Location.jsx

src文件夹中的文件会被翻译成普通的 JavaScript 文件并加上所生成的源映射。在这过程,--presets选项中的 es2015 和react 扮演着重要的角色。

理论上,从 ES5 标准下的代码中,我们应该可以通过命令require('Location.js')使得构件运作起来。但是,当我打开文件时,我发现这里并没有module.exports,而只是发现

exports.default = Location;

这将意味着我需要通过下面的命令来引入库:

require('Location').default;

很感谢地说,babel-plugin-add-module-exports 解决了该问题。因此,我把 NPM 脚本改成了如下:

./node_modules/.bin/babel ./src --out-dir ./lib
--source-maps --presets es2015,react
--plugins babel-plugin-add-module-exports

浏览器化

前面部分介绍所生成的是一个可被任何 JavaScript 项目导入或引用的文件。任何一个代码包装工具像 webpack 或 Browserify 都会解析所需要的依赖。但我最后考虑的一点是,如果开发人员不使用代码包装工具,那怎么办?简而言之,就是我们需要一个已经生成好的 JavaScript 文件,并直接可以使用 <script> 标签引入该文件到我的页面里。假设 React 已经加载到页面里,那么我只需要再把有着自动完成组件的构件引入到页面即可。

为了解决这个,我将会有效地利用了lib文件夹下的文件。这就是我之前所提的“浏览器化”。那么,我们来看看该怎么处理:

./node_modules/.bin/browserify ./lib/Location.js
-o ./build/react-place.js
--transform browserify-global-shim
--standalone ReactPlace

-o选项是用来指定输出文件。--standalone 选项是必须的,因为我并没有一个模块系统,所以该构件需要可全局访问。有趣的一点是--transform browserify-global-shim选项。这是一个转化加载项,其可用于排除 React 而只导入那个自动完成组件。为了使其工作,我需要像下面一样在package.js添加新的条目,:

// package.json
"browserify-global-shim": {
  "react": "React",
  "react-dom": "ReactDOM"
}

在此,我声明了一些全局变量的名字。而这些全局变量将会在调用构件里的require('react')require('react-dom')时被解析。当我们打开生成的build/react-place.js文件,我们将会看到:

var _react = (window.React);
var _reactDom = (window.ReactDOM);

在谈论把构件作为script>标签引入时,我想我们应该需要对其进行压缩。当然,在生产环境,我们还应该对build/react-place.js文件生成一个压缩版本。Uglifyjs 是一个不错的模块,其可用于压缩 JavaScript 代码。因此,我们只需要在“浏览器化”后调用即可:

./node_modules/.bin/uglifyjs ./build/react-place.js
--compress --mangle
--output ./build/react-place.min.js
--source-map ./build/react-place.min.js.map

结果

最后,所生成的脚本文件是一个结合了 Babel, Browserify 和 Uglifyjs三个模块的文件。

// package.json
"prepublish": "
  ./node_modules/.bin/babel ./src --out-dir ./lib --source-maps --presets es2015,react --plugins babel-plugin-add-module-exports &&
  ./node_modules/.bin/browserify ./lib/Location.js -o ./build/react-place.js --transform browserify-global-shim --standalone ReactPlace &&
  ./node_modules/.bin/uglifyjs ./build/react-place.js --compress --mangle --output ./build/react-place.min.js --source-map ./build/react-place.min.js.map
",

(注:为了使得脚本可读性更高,我把语句分成了几行。但是,在原来的 package.json 文件里,所有的语句都被摆放成一行。)

最后,项目里的文件夹/文件将如下所示:

|
+-- build
|   +-- react-place.js
|   +-- react-place.min.js
|   +-- react-place.min.js.map
+-- example-es6
|   +-- build
|   |   +-- app.js
|   |   +-- app.js.map
|   +-- src
|   |   +-- index.js
|   +-- index.html
+-- lib
|   +-- vendor
|   |   +-- google.js
|   |   +-- google.js.map
|   +-- Location.js
|   +-- Location.js.map
+-- src
    +-- vendor
    |   +-- google.js
    + -- Location.jsx





原文发布时间为:2015年12月28日


本文来自合作伙伴掘金,了解相关信息可以关注掘金网站。

时间: 2024-11-08 19:43:52

如何发布一个 React components的相关文章

How to Achieve Reusability with React Components - 如何实现 React 组件的可复用性 Back

本文讲的是How to Achieve Reusability with React Components - 如何实现 React 组件的可复用性 Back, 原文地址:How to Achieve Reusability with React Components 原文作者:Alex Grigoryan 译文出自:掘金翻译计划 译者:aleen42 校对者:Professor-Z.sqrthree.xiaoheiai4719 可复用性一词是当今软件工程领域上最为常见的流行词之一.可复用性早已

服务器-怎么发布一个做好的JSP网站

问题描述 怎么发布一个做好的JSP网站 我现在是网站做好了,打包成war文件了,有腾讯云服务器,有域名,服务器安装了IIS8,TOMCAT8. 该怎么做才能发布我的JSP的网站呢? 现在最大的问题是IIS吧80端口占了,只能用IIS8.0访问我的网站(ccxustc.com.cn). 怎么把IIS8根tomcat8整合起来共享端口80?或者禁用IIS,只用tomcat发布我的网站? 解决方案 把iis卸载,iis用不到 解决方案二: JTBC 做的一个小网站用Eclipse开发一个Jsp的网站

我想发布一个纯静态网页,html的。怎么弄到外网上?买什么空间好?

问题描述 我想发布一个纯静态网页,html的.怎么弄到外网上?买什么空间好? 我想发布一个纯静态网页,html的.怎么弄到外网上?买什么空间好? 解决方案 可以买阿里云或腾讯云这种,然后自己配置环境. 也可以使用git+hexo来搭建,完成免费 解决方案二: 简单的就是用Windows server系统 然后添加自带的IIS,里面创建一个网站,在设置时的路径放置你的网页,然后 外部服务器绑定内网和外网ip,接下来访问即可 解决方案三: 买阿里云,用不着配置多高,里面装个tomcat,把你的war

发布一个高效的JavaScript分析、压缩工具 JavaScript Analyser_javascript技巧

发布一个高效的JavaScript分析.压缩工具 JavaScript Analyser 先发一段脚本压缩示例,展示一下JSA语法压缩和优化功能. 复制代码 代码如下: try {         //xxxx();     }     catch (e) {         yyyy();         function f1() {         }     }     finally {         zzzz();     }     function f2(var1) {    

《React Native移动开发实战》一一1.4 第一个React Native应用

1.4 第一个React Native应用 颇费一番周折搭建好环境之后,终于可以长舒一口气,来开发第一个React Native应用了.1.4.1 初始化项目 首先,使用React Native命令行工具来初始化一个新的项目: react-native init ch02 等待工程创建成功并安装好所有依赖后,使用Atom打开ch02项目,来仔细瞧一瞧React Native项目结构,如图1.21所示. 图1.21 React Native项目结构 其中目录和文件的详细说明如表1.1所示. 回答:

请问一下webSphere如何只发布一个文件夹,及发布一个静态html文件,没有war包。

问题描述 请问一下webSphere如何只发布一个文件夹,及发布一个静态html文件,没有war包,请大家麻烦解答一下.提供下参考 解决方案 解决方案二:直接复制到相应的工程目录下,配置文件的话直接复制是不行的解决方案三:用wcf开发个就是的啊,,代码直接复制!解决方案四:这样的话没必要用WAS,直接一个HTTPSERVER就可以啦

我要发布一个image 怎么办呢

问题描述 A:我要发布一个image怎么办呢该问题来自CSDNDocker技术交流群(303806405),由版主xinshubiao整理. 解决方案 解决方案二:B:可以,只能是public的,private要收费A:不通过dockerhub.该怎么迁移image呢?B:用dockersave和dockerimport应该可以A:dockersave和dockerimport一个image以后,新的image不能跑容器,找不到命令C:好像要save和load配合用,找个私有的repositor

可在weblogic9.x控制台中发布一个WEB项目呀??

问题描述 我从这里http://localhost:7001/console登陆控制台中应该怎么发布一个WEB工程啊.需要拿myeclipse把这个web工程打成WAR包吗,还是怎么发布呢,最好给个详细过程,头一次用weblogic服务器,谢谢了. 解决方案 解决方案二:1.将你的项目导出war包2.登录http://localhost:7001/console,锁定并编辑3.点击左侧域结构中的部署,在右侧选择安装,一层层的选择,定位到你要安装的war包处4.保存所做的更改,并激活5.启动服务器

求救.如何用msbuild发布一个web application

问题描述 如何用微软的构建工具msbuild去发布一个webapplication找不到资料啊找到的都不是很有用处...