Webpack 一个前端工具,可以对 js/jsx/coffee/less/sass/图片等资源模块进行加载,预处理,再进行打包。
优点如下:
Webpack 将项目中用到的一切静态资源都视之为模块,模块之间可以互相依赖。Webpack 对它们进行统一的管理以及打包发布。
对 AMD/CMD 模式来说,模块是异步加载的,所以我们常规需要使用 define 函数来定义回调。
AMD,用过 RequireJS 的并不陌生,AMD 是在 CommonJS 的基础上考虑了浏览器的异步加载特性而产生的,可以让模块异步加载并保证执行顺序。
|
|
CMD,用过 SeaJS 的小伙伴是不是很熟悉。
|
|
webpack 遵循 commonJS 语法,无须任何 define ,这种方式语法更加简洁直观。
|
|
CommonJS 的 require 函数虽是同步加载,但浏览器并不同步加载该模块,对 require 的处理是由 Webpack 进行解析和打包的(类似 browserify),浏览器只需要执行打包后的代码。但是对于 React 中的 JSX 语法,这就需要使用 Webpack 的扩展加载器来处理了,如 jsx-loader。
1.全局安装
执行命令:npm install webpack -g
2.项目依赖安装
执行命令:npm install webpack --save-dev
node_modules 文件夹中会包含 webpack,此时可以使用 webpack 命令了
3.生成 package.json 文件
根目录下执行命令:npm init
4.安装插件
若 package.json 文件已配置好,根目录下执行命令:npm install
配置文件 webpack.config.js,好比 Gulpfile.js 或 Gruntfile.js,用来配置项目,告 诉webpack 需要做哪些操作。
一个简单的 webpack.config.js 代码如下:
|
|
entry
: 入口文件,比如我这边的入口文件时 main.jsoutput
: 目标文件,我这边是在根目录下生成 assets/build/js 文件夹,该文件夹内有 [name].bundle.js 文件; output.path: 打包文件存放的绝对路径;
output.publicPath: 网站运行时的访问路径;
output.filename: 打包后的文件名;resolve
: 解析模块路径;
root:绝对路径;
extensions:可以用来指定模块的后缀,这样在引入模块时就不需要写后缀,会自动补全;
alias:别名,直接require别名;plugins
: 定义了需要使用的插件,比如 commonsPlugin 在打包多个入口文件时会提取公用的部分。module.loaders
:文件加载器,对相应文件需要使用什么加载器来处理,比如 jsx-loader 加载器处理 jsx 文件,还有 style-loader 和 css-loader 加载器,处理样式文件。
加载器安装
|
|
更多详情参见:configuration
|
|
如命令:webpack –display-modules –profile –colors
main.html 代码如下:
|
|
main.js 代码如下:
|
|
到此,webpack 都配置好了,执行行命令:webpack,ok
Webpack 将所有静态资源都认为是模块,比如 js,jsx,css,scss,图片等,从而可以对其进行统一管理,通过对应的加载器处理成模块。
Webpack 的加载器之间可以进行串联,一个加载器的输出可以成为另一个加载器的输入。比如 less 文件先通过 less-loader
处理成 css,然后再通过 css-loader
加载成css模块,最后由 style-loader
加载器对其做最后的处理,通过 style
标签将其应用到最终的浏览器环境。
为了让Webpack识别什么样的资源应该用什么加载器去载入,需要在配置文件进行配置,通过正则表达式对文件名进行匹配。例如:
|
|
加载器之间的级联是通过 ! 来连接,例如:style-loader!css-loader!less-loader。”-loader” 可以省略,如:style!css!less。
jsx 文件由 jsx-loader 处理,加载器支持参数,?harmony 参数使其支持ES6语法。当然也可以用 babel-loader
图片资源,由 url-loader 实现,代码中 url-loader?limit=8192 小于 8k 的图片转为 Base64。
更多详情参见:loaders,list-of-loaders
别名 resolve.alias
,把一个请求重定向到另一个路径,如下:
|
|
require(‘jquery’),其实就等价于 require(‘./assets/js/lib/jquery-2.2.0.min.js’)。
使用 CommonsChunkPlugin
插件来提取多个页面之间的公共模块,并将该模块打包为 common.js 。配置如下:
|
|
entry
: 入口文件增加 entry.main, entry.form, entry.vendorplugins
: 插件项增加 new CommonsChunkPlugin
最终将生成公共模块文件 js/vendor.js
更多详情参见:code-splitting
样式会被默认打包到 js 文件中,怎么独立出来作为单独样式文件,然后在页面中用 link
标签引入。
用插件 extract-text-webpack-plugin
|
|
module.loaders
增加 { test: /.css$/,loader: ExtractTextPlugin.extract(“style-loader”, “css-loader”)}plugins
: 插件项增加 new ExtractTextPlugin(“css/[name].css”)
最终将生成公共模块文件 css/main.css 和 css/form.css
更多详情参见:stylesheets
为减少加载时间,可能要将项目打包成多个资源文件,怎么办呢?创建多个入口文件:如下:
|
|
打包后,会生成三个文件,分别为:main.bundle.js, form.bundle.js, vendor.js
更多详情参见:code-splitting
图片资源由 url-loader
来加载的,既可以是 css 文件里 url 属性,也可以是 require 请求,如下:
|
|
|
|
webpack.config.js 配置如下:
|
|
小于 8k 的图片会转化为 base64,否则,在 ./assets/build/images 目录下生成相应的图片。此时要注意 output.publicPath 的配置,若为空,则为根目录,有可能导致打包后的图片路径找不到。
使用 require.ensure
,当需要时再加载,如下:
|
|
更多详情参见:code-splitting
有些文件我们并不希望被打包,而是以CDN方式并以 script
的形式引用,但在 webpack 中又可以正常使用。怎么办呢?请用 externals 声明外部依赖。
|
|
更多详情参见:library-and-externals
webpack 可以与 gulp 配合,一起使用,配置如下:
|
|
执行命令:gulp webpack
,ok
更多详情参见:usage-with-gulp
一个简单的 React 组件,module.js 代码如下:
|
|
在 main.js 中引入 module.js
|
|
这时,main.js 和 module.js 都是JSX语法,需要对它们进行预处理,这就要引入 JSX 加载器。配置文件中加入如下配置:
|
|
Webpack 提供了一个轻量的 node.js express 服务器,开发过程中,监听文件变化,实时打包,通过 socket.io 通知客户端,实现页面的自动刷新。
首先,执行安装命令:npm install webpack-dev-server --save-dev
启动开发服务器,运行命令:webpack-dev-server
,请看控制台日志,然后访问 localhost:8080/webpack-dev-server
。改变相应 js 中的内容,保存,看页面,有效果了。再看看控制台输出日志,自动编译哦,然后把编译结果通知客户端更新。
更多详情参见:webpack-dev-server
Webpack 有运行时模块替换功能,称之为 Hot Module Replacement (HMR)。当某个模块代码发生变化时,Webpack 实时打包将其推送到页面并进行替换,从而无需刷新页面就实现代码替换。
在 React 开发中,针对 React 出现了一个第三方 react-hot-loader
加载器,可以轻松实现 React 组件的热替换。因为 React 的每一次更新都是全局刷新虚拟 DOM,让 React 组件的热替换可以成为通用的加载器,从而极大提高开发效率。
首先,执行安装命令:npm install react-hot-loader —save-dev
webpack-dev-server 需要开启 HMR 参数 hot,下面创建一个 server.js 文件启动 Webpack 开发服务器,代码如下:
server.js
|
|
除了 server.js 外,webpack.config.js 还需要如下修改:
|
|
entry.index
:配置 webpack 开发服务器,接收 Webpack 的推送,通知相关 React 组件进行重新 Render。module.loaders
:Webpack 用 react-hot-loader 加载 React 组件。plugins
:加上热替换的插件和防止报错的插件。
执行命令:node server.js
,ok,资源的任何修改,无需刷新页面,即可重新宣染。
更多详情参见:react-hot-loader
React 是一个 Facebook 和 Instagram 用来创建用户界面的 JavaScript 库。 我们以 react 为库来创建组件,组件有自己的结构、逻辑、样式,会依赖一些资源,或依赖其他组件。
用 React 写组件的时候,通常会用到 JSX 语法,HTML 语言直接写在 JavaScript 语言之中,被 JSX 转换工具转换成纯 Javascript 代码,当然你想直接使用纯 Javascript 代码写也是可以的,只是利用 JSX,组件的结构和组件之间的关系看上去更加清晰。
|
|
通过 JavaScript 直接生成模板,这样你就可以用一个真正语言的所有表达能力去构建用户界面。为了使这变得更简单,我们做了一个非常简单、可选类似 HTML 语法 ,通过函数调用即可生成模板的编译器,称为 JSX。
文件分离
你的 React JSX 代码文件可以写在另外的文件里。新建下面的 helloworld.js。
然后在 helloworld.html 引用该文件:<script type="text/jsx" src="./helloworld.js"></script>
JSX 转换,下面 JSX 代码:
转化后:
React.createElement 这个方法有三个参数,第一个参数可以是一个字符串,表示是一个HTML标准内的元素,或者是一个 ReactClass 类型的对象,表示我们之前封装好的自定义组件。第二个参数是一个对象,它保存了这个元素的所有固有属性;从第三个参数,内容或子元素。
把JSX语法的代码转化为纯 Javascript 代码,有多种方式。
1、对于内联与 HTML 中的代码或者是未经过转化的外部文件,在 script 标签中要加上 type=”text/jsx”,并引入 JSXTransformer.js 文件即可,不过这种方式并不建议在生产环境使用,建议的方法是在代码上线前就将代码转换好。
2、也可以使用 npm 全局安装 react-tools
:npm install -g react-tools
执行命令:jsx src/ build/
若想监听文件变化并自动编译,可执行命令:jsx --watch src/ build/
3、如果使用自动化工具,比如 gulp 的话,可以使用相应插件 gulp-react。
更多详情参见:jsx-in-depth
React 可以渲染 HTML 标签 (strings) 或 React 模块 (classes)。
要渲染 HTML 标签,只需在 JSX 里使用小写字母开头的标签名。要创建一个 HTML 标准中存在的元素,直接像写 HTML 代码一样即可:
|
|
要渲染 React 模块,只需创建一个大写字母开头的本地变量。
|
|
React 的 JSX 里约定分别使用首字母大、小写来区分本地模块的类和 HTML 标签。
不过需要注意的是 class 和 for 这两个属性,由于 JSX 就是 JavaScript,一些标识符像 class 和 for 不建议作为 XML 属性名。作为替代,React DOM 使用 className 和 htmlFor 来做对应的属性。
还有一点是,在创建 HTML 标准内的元素时,JSX 转化器会丢弃那些非标准的属性,如果一定要添加自定义属性,那么需要在这些自定义属性之前添加 data- 前缀。
|
|
在 JSX 语法中,要使用 JavaScript 表达式作为属性值,只需把这个表达式用一对大括号 ({}) 包起来,不要用引号 (“”)。 比如下面这个使用三目运算符的例子:
|
|
更多详情参见:jsx-in-depth
JSX 里添加注释很容易;它们只是 JS 表达式而已。你只需要在一个标签的子节点内(非最外层)小心地用 {} 包围要注释的部分。
|
|
在 JSX 中,可以使用 … 运算符,表示将一个对象的键值对与 ReactElement 的 props 属性合并,这个 … 运算符的实现类似于 ES6 Array 中的 … 运算符的特性。
|
|
相当于:
|
|
它也可以和普通的XML属性混合使用,需要同名属性,后者将覆盖前者:
|
|
更多详情参见:jsx-spread
组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM 上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。
但是,有时需要从组件获取真实 DOM 的节点,这时就要用到 ref 属性
|
|
需要注意的是,由于 this.refs.[refName] 属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。
更多详情参见:more-about-refs
React 为每个状态都提供了两种处理函数,will 函数在进入状态之前调用,did 函数在进入状态之后调用,三种状态共计五种处理函数。
|
|
更多详情参见:lifecycle-methods
React 组件非常简单。你可以认为它们就是简单的函数,接受 props 和 state 作为参数,然后渲染出 HTML。正是因为它们是这么的简单,这使得它们非常容易理解。
注意: 有一个限制,React 组件只能渲染单个根节点。如果你想要返回多个节点,它们必须被包含在同一个节点里。
还有很多内容,待续…
基于 React
组件化开发,CommonJS
规范编写代码, 用 gulp
和 webpack
自动化打包。
项目:https://github.com/ifootmark/fm-react
Demo:https://ifootmark.github.io/fm-react/demo
快速构建项目,组件化、模块化、自动化,一条命令打包发布。
项目:https://github.com/ifootmark/fm-build-quickstart
Angular 2,本项目包括 ES6、TypeScript、模板、数据绑定、组件、类、服务、依赖注入、路由、组件间通信等以及用 webpack 打包发布。
项目:https://github.com/ifootmark/fm-angular2
Demo:https://ifootmark.github.io/fm-angular2/ng2/index
EmberJS, MVC 框架,本项目包括模板、视图、数据绑定、控制器、模型、路由、承诺等以及用 Grunt 打包发布。
项目:https://github.com/ifootmark/fm-ember
Demo:https://ifootmark.github.io/fm-ember
基于 NodeJS+Express 的反向代理,可实现跨域访问、记录日志、数据跟踪等。
项目:https://github.com/ifootmark/fm-node-proxy
npm 包:https://www.npmjs.com/package/fm-node-proxy
简单自用 dialog 对话框。
项目:https://github.com/ifootmark/fm-dialog
Demo:http://ifootmark.github.io/fm-dialog/demo.html
npm 包:https://www.npmjs.com/package/fm-dialog
对 localStorage 封闭,方便调用,调用方法请查看 API。
项目:https://github.com/ifootmark/fm-localstorage
Demo:http://ifootmark.github.io/fm-localstorage/test/index.html
npm 包:https://www.npmjs.com/package/fm-localstorage
对 IndexedDB 封闭,方便调用,调用方法请查看 API。
项目:https://github.com/ifootmark/fm-indexeddb
Demo:http://ifootmark.github.io/fm-indexeddb/test/index.html
npm 包:https://www.npmjs.com/package/fm-indexeddb