-
Notifications
You must be signed in to change notification settings - Fork 547
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
从零搭建React全家桶框架教程 #1
Comments
webpack 公共配置 |
博主在打包这里没有讲清楚,webpack没有全局安装的话 webpack --config webpack.dev.config.js 命令会出错。要么全局安装,要么运行命令./node_modules/.bin/webpack --config webpack.dev.config.js |
@STMU1320 确实是,sorry。没注意~~ 谢谢谢谢。 |
|
命令优化 处,应该是执行 |
@surpass-wei 哈哈哈哈哈。谢谢谢谢。。已经改了。 之前我的 |
一般运行我建议,npm run dev, 发布测试版本包交npm run testbuild,正式版本叫npm run build。这样挺好 |
@yeliping 我看别人写的,基本一般运行都是 |
我公司的vue框架,不是我搭的。在npm run testbuild和npm run build有区别的,区别就在于,打包了测试和正式环境,那些接口地址就不一样。免得混淆,测试地址上了正式地址的错误。楼主你那个打包压缩没弄错zip这种格式吧 |
@yeliping 打包压缩不是打包压缩成zip呀。。。没有这一步。 压缩是指代码压缩~ |
我知道是指代码压缩呀,弄错zip这些可以再配置的 |
@yeliping 恩恩。下一步 我可以做这个。嘿嘿。 |
`'use strict'; var exports = {
}; module.exports = exports;` 这个文件就是用来配置测试环境或者正式环境。主要是以前有个新同事把测试发到正式,导致出现大问题.所以他们弄了这样的配置 |
@yeliping 我们开发时就没个问题的。可以把 |
@yeliping 当然因项目而异啦。 |
在
|
@ranjin 祝你好运。 |
也就是说 如果配置的是 |
@ranjin 可以加,也可以不加。 如果不加的话 就默认8080哦。 |
向后台请求用户基本信息为例的例子中,一会是 |
@surpass-wei 确实是写错了。已经修正。谢谢你。 |
看了一半了,不过概念性的东西实在太多了。 |
@ranjin 从我接触react到现在,也有快一年了吧。。。慢慢来,你先学会用别人搭好的现成的框架。熟悉怎么用之后,再来看怎么搭框架。 |
嗯嗯。现在就是在看您这整个框架的。然后再慢慢来学习一些知识点的。 |
@ranjin JSX |
嘿嘿,看了博主文章自己弄了一个,删了一些跟我项目不是很必要的东西,自己改了一点,不过总体还是挺好的。谢谢博主啦。redux我还是去补补,因为之前没怎么接触过。以前一直用angular1.x和vue、jq做项目 |
@yeliping 我也感觉redux好绕啊。 |
@ranjin 是的,我最开始也不理解。 先学会用,用着用着就懂原理了。~你要明白, |
写的真的很不错,花了几个小时跟着走了一遍。以前项目都是脚手架create-react-app直接搭的。 |
不过感觉react-redux那块还可以详尽一点,多创建一个container,纯显示组件就放component里就行。逻辑相关的放container。 这样相信新手就可以少走弯路了:》 |
不建议在代码中使用mock, 使用rap这种更好,楼主可以尝试下命令行工具,自动生成这些模板,可以选择工具, 状态管理之类的,或者简单的配置,比如需要 scss, 直接指定就可以, |
webpack-dev-server --config webpack.dev.config.js |
写的太棒了 |
很感谢,入门很有用,理解也深刻。 |
不知道为什么我卡在了webpack打包React那里了,用的是最新的webpack4.0 cli3 下面是错误
| );** |
webpack打包的时候如果使用的jsx写法就是错误的,这个怎么解决捏 Hello React! , document.getElementById('app')
| );**
|
缺少编译loader吧,webpack配置里添加 babel-loader, .babelrc文件 配置支持file-loader,上面有说到的 |
我添加了,也是不得,而且我是直接复制的。 好像是babel-loader自己的问题 我也不懂。 你碰到过这个问题吗 |
按需加载导致不能热更新怎么解决呢? |
这个不太懂,估计是因为你的依赖版本不一样吧。 这个较承你参考已一下就可以了。 自己用webpack搭建。 我现在就是这样。 毕竟这个教程是两年前的。 Webpack也升级了 配置有了一些改动
发送自 Windows 10 版邮件<https://go.microsoft.com/fwlink/?LinkId=550986>应用
发件人: zl<mailto:notifications@github.com>
发送时间: 2019年12月6日 11:38
收件人: brickspert/blog<mailto:blog@noreply.github.com>
抄送: GreenKing19<mailto:greenking19@outlook.com>; Comment<mailto:comment@noreply.github.com>
主题: Re: [brickspert/blog] 从零搭建React全家桶框架教程 (#1)
按需加载导致不能热更新怎么解决呢?
―
You are receiving this because you commented.
Reply to this email directly, view it on GitHub<#1?email_source=notifications&email_token=AKKTGFGNYQUHALRJNDT3SJDQXHCJ5A5CNFSM4DZLOQCKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEGC5K6Q#issuecomment-562419066>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AKKTGFGJ3JGY6TCU4CUSDPDQXHCJ5ANCNFSM4DZLOQCA>.
|
|
优秀 |
写的好详细,点赞 |
很适合有一点基础的react开发人员学习,谢谢 |
挺好的。花了一天时间也搭配了一个react+webpack+ts |
TypeError: Cannot read property 'make' of undefined |
OK,是版本问题,毕竟相差三年,很多插件都多少有变化 |
最好还是自己去webpack查看react配置吧。 很简单
发自我的iPhone
在 2020年5月18日,下午5:01,ningy123 <notifications@github.com> 写道:
TypeError: Cannot read property 'make' of undefined
at PersistentChildCompilerSingletonPlugin.apply
在HtmlWebpackPlugin这一步后出错了,就是缓存那部分做了后,添加这个配置,然后yarn start,报这个错误。有大佬给个提示吗?
OK,是版本问题,毕竟相差三年,很多插件都多少有变化
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub<#1 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AKKTGFA6ONPZXYR6E7BENP3RSD2NFANCNFSM4DZLOQCA>.
|
mark |
我已经收到你的邮件啦~,表着急,待我仔细查看
|
您好,您的邮件已收到,谢谢This is an automatic reply, confirming that your e-mail was received.Thank you.
|
小冉已经收到你的邮件啦~
|
从零搭建React全家桶框架教程
关注公众号「前端技术砖家」,拉你进交流群,大家一起共同交流和进步。
源码地址:https://github.com/brickspert/react-family
提问反馈:blog
因为本教程写于2017年9月,然而前端技术发展太快了。有些库的版本一直在升级,所以你如果碰到奇怪的问题,请先检查下安装的库版本是否和我源码中的一样。please~
大家阅读的时候,照着目录来阅读哦,有些章节不在文章里面。要点链接的~
目录
axios
和middleware
优化API请求webpack
公共配置 webpack-common-config(2017-09-04)当我第一次跟着项目做
react
项目的时候,由于半截加入的,对框架了解甚少,只能跟着别人的样板写。对整个框架没有一点了解。做项目,总是要解决各种问题的,所以每个地方都需要去了解,但是对整个框架没有一个整体的了解,实在是不行。
期间,我也跟着别人的搭建框架的教程一步一步的走,但是经常因为自己太菜,走不下去。在经过各种蹂躏之后,对整个框架也有一个大概的了解,
我就想把他写下来,让后来的菜鸟能跟着我的教程对
react
全家桶有一个全面的认识。我的这个教程,从新建根文件夹开始,到成型的框架,每个文件为什么要建立?建立了干什么?每个依赖都是干什么的?一步一步写下来,供大家学习。
当然,这个框架我以后会一直维护的,也希望大家能一起来完善这个框架,如果您有任何建议,欢迎在这里留言,欢迎
fork
源码react-family。我基于该框架
react-family
又做了一个兼容IE8的版本,教程在这里react-family框架兼容IE8教程。创建文件夹并进入
mkdir react-family && cd react-family
init npm
npm init
按照提示填写项目基本信息安装
webpack
npm install --save-dev webpack@3
Q: 什么时候用
--save-dev
,什么时候用--save
?A:
--save-dev
是你开发时候依赖的东西,--save
是你发布之后还依赖的东西。看这里根据webpack文档编写最基础的配置文件
新建
webpack
开发配置文件touch webpack.dev.config.js
webpack.dev.config.js
学会使用
webpack
编译文件新建入口文件
mkdir src && touch ./src/index.js
src/index.js
添加内容document.getElementById('app').innerHTML = "Webpack works"
现在我们执行命令
webpack --config webpack.dev.config.js
我们可以看到生成了
dist
文件夹和bundle.js
。现在我们测试下~
dist
文件夹下面新建一个index.html
touch ./dist/index.html
dist/index.html
填写内容用浏览器打开
index.html
,可以看到Webpack works
!现在回头看下,我们做了什么或者说
webpack
做了什么。把入口文件
index.js
经过处理之后,生成bundle.js
。就这么简单。通俗的说,就是我们可以用ES6, ES7等来编写代码,Babel会把他们统统转为ES5。
babel-core 调用Babel的API进行转码
babel-loader
babel-preset-es2015 用于解析 ES6
babel-preset-react 用于解析 JSX
babel-preset-stage-0 用于解析 ES7 提案
npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react babel-preset-stage-0
新建
babel
配置文件.babelrc
touch .babelrc
.babelrc
修改
webpack.dev.config.js
,增加babel-loader
!现在我们简单测试下,是否能正确转义ES6~
修改
src/index.js
执行打包命令
webpack --config webpack.dev.config.js
浏览器打开
index.html
,我们看到正确输出了我现在在使用Babel!
然后我们打开打包后的
bundle.js
,翻页到最下面,可以看到箭头函数被转换成普通函数了!Q:
babel-preset-state-0
,babel-preset-state-1
,babel-preset-state-2
,babel-preset-state-3
有什么区别?A: 每一级包含上一级的功能,比如
state-0
包含state-1
的功能,以此类推。state-0
功能最全。具体可以看这篇文章:babel配置-各阶段的stage的区别参考地址:
https://segmentfault.com/a/1190000008159877
http://www.ruanyifeng.com/blog/2016/01/babel.html
npm install --save react react-dom
修改
src/index.js
使用react
执行打包命令
webpack --config webpack.dev.config.js
打开
index.html
看效果。我们简单做下改进,把
Hello React
放到组件里面。体现组件化~按照React语法,写一个Hello组件
然后让我们修改
src/index.js
,引用Hello
组件!src/index.js
在根目录执行打包命令
webpack --config webpack.dev.config.js
打开
index.html
看效果咯~Q:每次打包都得在根目录执行这么一长串命令
webpack --config webpack.dev.config.js
,能不打这么长吗?A:修改
package.json
里面的script
,增加dev-build
。package.json
现在我们打包只需要执行
npm run dev-build
就可以啦!参考地址:
http://www.ruanyifeng.com/blog/2016/10/npm_scripts.html
npm install --save react-router-dom
新建
router
文件夹和组件按照
react-router
文档编辑一个最基本的router.js
。包含两个页面home
和page1
。src/router/router.js
新建页面文件夹
新建两个页面
Home
,Page1
填充内容:
src/pages/Home/Home.js
Page1.js
现在路由和页面建好了,我们在入口文件
src/index.js
引用Router。修改
src/index.js
现在执行打包命令
npm run dev-build
。打开index.html
查看效果啦!那么问题来了~我们发现点击‘首页’和‘Page1’没有反应。不要惊慌,这是正常的。
我们之前一直用这个路径访问
index.html
,类似这样:file:///F:/react/react-family/dist/index.html
。这种路径了,不是我们想象中的路由那样的路径
http://localhost:3000
~我们需要配置一个简单的WEB服务器,指向index.html
~有下面两种方法来实现Nginx
,Apache
,IIS
等配置启动一个简单的的WEB服务器。webpack-dev-server
来配置启动WEB服务器。下一节,我们来使用第二种方法启动服务器。这一节的DEMO,先放这里。
参考地址
简单来说,
webpack-dev-server
就是一个小型的静态文件服务器。使用它,可以为webpack
打包生成的资源文件提供Web服务。npm install webpack-dev-server@2 --save-dev
修改
webpack.dev.config.js
,增加webpack-dev-server
的配置。webpack.dev.config.js
现在执行
webpack-dev-server --config webpack.dev.config.js
浏览器打开http://localhost:8080,OK,现在我们可以点击
首页
,Page1
了,看URL地址变化啦!我们看到
react-router
已经成功了哦。Q:
--content-base
是什么?A:
URL的根目录。如果不设定的话,默认指向项目根目录。
重要提示:webpack-dev-server编译后的文件,都存储在内存中,我们并不能看见的。你可以删除之前遗留的文件
dist/bundle.js
,仍然能正常打开网站!
每次执行
webpack-dev-server --config webpack.dev.config.js
,要打很长的命令,我们修改package.json
,增加script->start
:下次执行
npm start
就可以了。既然用到了
webpack-dev-server
,我们就看看它的其他的配置项。看了之后,发现有几个我们可以用的。
console
中打印彩色日志404
响应都被替代为index.html
。有什么用呢?你现在运行npm start
,然后打开浏览器,访问http://localhost:8080
,然后点击Page1
到链接http://localhost:8080/page1
,然后刷新页面试试。是不是发现刷新后
404
了。为什么?dist
文件夹里面并没有page1.html
,当然会404
了,所以我们需要配置historyApiFallback
,让所有的404
定位到index.html
。host
,默认是localhost
。如果你希望服务器外部可以访问,指定如下:host: "0.0.0.0"
。比如你用手机通过IP访问。Webpack
的模块热替换特性。关于热模块替换,我下一小节专门讲解一下。8080
端口。localhost:3000
上有后端服务的话,你可以这样启用代理:根据这几个配置,修改下我们的
webpack-dev-server
的配置~webpack.dev.config.js
CLI ONLY
的需要在命令行中配置package.json
现在我们执行
npm start
看看效果。是不是看到打包的时候有百分比进度?在http://localhost:8080/page1
页面刷新是不是没问题了?用手机通过局域网IP是否可以访问到网站?
参考地址:
到目前,当我们修改代码的时候,浏览器会自动刷新,不信你可以去试试。(如果你的不会刷新,看看这个调整文本编辑器)
我相信看这个教程的人,应该用过别人的框架。我们在修改代码的时候,浏览器不会刷新,只会更新自己修改的那一块。我们也要实现这个效果。
我们看下webpack模块热替换教程。
我们接下来要这么修改
package.json
增加--hot
src/index.js
增加module.hot.accept()
,如下。当模块更新的时候,通知index.js
。src/index.js
现在我们执行
npm start
,打开浏览器,修改Home.js
,看是不是不刷新页面的情况下,内容更新了?惊不惊喜?意不意外?做模块热替换,我们只改了几行代码,非常简单的。纸老虎一个~
现在我需要说明下我们命令行使用的
--hot
,可以通过配置webpack.dev.config.js
来替换,向文档上那样,修改下面三处。但我们还是用
--hot
吧。下面的方式我们知道一下就行,我们不用。同样的效果。HRM
配置其实有两种方式,一种CLI
方式,一种Node.js API
方式。我们用到的就是CLI
方式,比较简单。Node.js API
方式,就是建一个server.js
等等,网上大部分教程都是这种方式,这里不做讲解了。你以为模块热替换到这里就结束了?no
nono~上面的配置对
react
模块的支持不是很好哦。例如下面的
demo
,当模块热替换的时候,state
会重置,这不是我们想要的。修改
Home.js
,增加计数state
src/pages/Home/Home.js
你可以测试一下,当我们修改代码的时候,
webpack
在更新页面的时候,也把count
初始为0了。为了在
react
模块更新的同时,能保留state
等页面中其他状态,我们需要引入react-hot-loader~Q: 请问
webpack-dev-server
与react-hot-loader
两者的热替换有什么区别?A: 区别在于
webpack-dev-serve
r自己的--hot
模式只能即时刷新页面,但状态保存不住。因为React
有一些自己语法(JSX)是HotModuleReplacementPlugin
搞不定的。而
react-hot-loader
在--hot
基础上做了额外的处理,来保证状态可以存下来。(来自segmentfault)下面我们来加入
react-hot-loader v3
,安装依赖
npm install react-hot-loader@next --save-dev
根据文档,
我们要做如下几个修改~
.babelrc
增加react-hot-loader/babel
.babelrc
webpack.dev.config.js
入口增加react-hot-loader/patch
webpack.dev.config.js
src/index.js
修改如下src/index.js
现在,执行
npm start
,试试。是不是修改页面的时候,state
不更新了?参考文章:
做到这里,我们简单休息下。做下优化~
在之前写的代码中,我们引用组件,或者页面时候,写的是相对路径~
比如
src/router/router.js
里面,引用Home.js
的时候就用的相对路径webpack提供了一个别名配置,就是我们无论在哪个路径下,引用都可以这样
下面我们来配置下,修改
webpack.dev.config.js
,增加别名~webpack.dev.config.js
然后我们把之前使用的绝对路径统统改掉。
src/router/router.js
src/index.js
我们这里约定,下面,我们会默认配置需要的别名路径,不再做重复的讲述哦。
接下来,我们就要就要就要集成
redux
了。要对
redux
有一个大概的认识,可以阅读阮一峰前辈的Redux 入门教程(一):基本用法如果要对
redux
有一个非常详细的认识,我推荐阅读中文文档,写的非常好。读了这个教程,有一个非常深刻的感觉,redux
并没有任何魔法。不要被各种关于 reducers, middleware, store 的演讲所蒙蔽 ---- Redux 实际是非常简单的。
当然,我这篇文章是写给新手的,如果看不懂上面的文章,或者不想看,没关系。先会用,多用用就知道原理了。
开始整代码!我们就做一个最简单的计数器。自增,自减,重置。
先安装
redux
npm install --save redux
初始化目录结构
先来写
action
创建函数。通过action
创建函数,可以创建action
~src/redux/actions/counter.js
再来写
reducer
,reducer
是一个纯函数,接收action
和旧的state
,生成新的state
.src/redux/reducers/counter.js
一个项目有很多的
reducers
,我们要把他们整合到一起src/redux/reducers.js
到这里,我们必须再理解下一句话。
reducer
就是纯函数,接收state
和action
,然后返回一个新的state
。看看上面的代码,无论是
combineReducers
函数也好,还是reducer
函数也好,都是接收state
和action
,返回更新后的
state
。区别就是combineReducers
函数是处理整棵树,reducer
函数是处理树的某一点。接下来,我们要创建一个
store
。前面我们可以使用
action
来描述“发生了什么”,使用action
创建函数来返回action
。还可以使用
reducers
来根据action
更新state
。那我们如何提交
action
?提交的时候,怎么才能触发reducers
呢?store
就是把它们联系到一起的对象。store
有以下职责:state
;getState()
方法获取state
;dispatch(action)
触发reducers
方法更新state
;subscribe(listener)
注册监听器;subscribe(listener)
返回的函数注销监听器。src/redux/store.js
到现在为止,我们已经可以使用
redux
了~下面我们就简单的测试下
src/redux/testRedux.js
当前文件夹执行命令
是不是看到输出了
state
变化?做这个测试,就是为了告诉大家,
redux
和react
没关系,虽说他俩能合作。到这里,我建议你再理下
redux
的数据流,看看这里。store.dispatch(action)
提交action
。redux store
调用传入的reducer
函数。把当前的state
和action
传进去。reducer
应该把多个子reducer
输出合并成一个单一的state
树。Redux store
保存了根reducer
返回的完整state
树。就是酱紫~~
这会
webpack.dev.config.js
路径别名增加一下,后面好写了。webpack.dev.config.js
把前面的相对路径都改改。
下面我们开始搭配
react
使用。写一个
Counter
页面src/pages/Counter/Counter.js
修改路由,增加
Counter
src/router/router.js
npm start
看看效果。下一步,我们让
Counter
组件和Redux
联合起来。使Counter
能获得到Redux
的state
,并且能发射action
。当然我们可以使用刚才测试
testRedux
的方法,手动监听~手动引入store
~但是这肯定很麻烦哦。react-redux
提供了一个方法connect
。connect
接收两个参数,一个mapStateToProps
,就是把redux
的state
,转为组件的Props
,还有一个参数是mapDispatchToprops
,就是把发射
actions
的方法,转为Props
属性函数。先来安装
react-redux
npm install --save react-redux
src/pages/Counter/Counter.js
下面我们要传入
store
src/index.js
到这里我们就可以执行
npm start
,打开localhost:8080/counter看效果了。但是你发现
npm start
一直报错WTF?这个错误困扰了半天。我说下为什么造成这个错误。我们引用
redux
的时候这样用的import {createStore} from 'redux'
然而,我们在
webapck.dev.config.js
里面这样配置了然后
webapck
编译的时候碰到redux
都去src/redux
去找了。但是找不到啊。所以我们把webpack.dev.config.js
里面redux
这一行删除了,就好了。并且把使用我们自己使用
redux
文件夹的地方改成相对路径哦。现在你可以
npm start
去看效果了。这里我们再缕下(可以读React 实践心得:react-redux 之 connect 方法详解)
Provider
组件是让所有的组件可以访问到store
。不用手动去传。也不用手动去监听。connect
函数作用是从Redux state
树中读取部分数据,并通过 props 来把这些数据提供给要渲染的组件。也传递dispatch(action)
函数到props
。接下来,我们要说异步
action
参考地址: http://cn.redux.js.org/docs/advanced/AsyncActions.html
想象一下我们调用一个异步
get
请求去后台请求数据:isLoading
置为true
。isLoading
置为false
,data
填充数据。isLoading
置为false
,显示错误信息。下面,我们以向后台请求用户基本信息为例。
user.json
,等会请求用,相当于后台的API接口。dist/api/user.json
action
创建函数。src/redux/actions/userInfo.js
我们创建了请求中,请求成功,请求失败三个
action
创建函数。reducer
再强调下,
reducer
是根据state
和action
生成新state
的纯函数。src/redux/reducers/userInfo.js
这里的
...state
语法,是和别人的Object.assign()
起同一个作用,合并新旧state。我们这里是没效果的,但是我建议都写上这个哦组合
reducer
src/redux/reducers.js
action
,有了reducer
,我们就需要调用把action
里面的三个action
函数和网络请求结合起来。dispatch getUserInfoRequest
dispatch getUserInfoSuccess
dispatch getUserInfoFail
src/redux/actions/userInfo.js
增加我们这里发现,别的
action
创建函数都是返回action
对象:但是我们现在的这个
action
创建函数getUserInfo
则是返回函数了。为了让
action
创建函数除了返回action
对象外,还可以返回函数,我们需要引用redux-thunk
。npm install --save redux-thunk
这里涉及到
redux
中间件middleware
,我后面会讲到的。你也可以读这里Middleware。简单的说,中间件就是
action
在到达reducer
,先经过中间件处理。我们之前知道reducer
能处理的action
只有这样的{type:xxx}
,所以我们使用中间件来处理函数形式的
action
,把他们转为标准的action
给reducer
。这是redux-thunk
的作用。使用
redux-thunk
中间件我们来引入
redux-thunk
中间件src/redux/store.js
到这里,
redux
这边OK了,我们来写个组件验证下。src/pages/UserInfo/UserInfo.js
这里你可能发现
connect
参数写法不一样了,mapStateToProps
函数用了es6
简写,mapDispatchToProps
用了react-redux
提供的简单写法。增加路由
src/router/router.js
现在你可以执行
npm start
去看效果啦!到这里
redux
集成基本告一段落了,后面我们还会有一些优化。combinReducers优化
redux
提供了一个combineReducers
函数来合并reducer
,不用我们自己合并哦。写起来简单,但是意思和我们自己写的
combinReducers
也是一样的。src/redux/reducers.js
现在我们发现一个问题,代码哪里写错了,浏览器报错只报在
build.js
第几行。这让我们分析错误无从下手。看这里。
我们增加
webpack
配置devtool
!webpack.dev.config.js
增加devtool: 'inline-source-map'
这次看错误信息是不是提示的很详细了?
同时,我们在
srouce
里面能看到我们写的代码,也能打断点调试哦~先说这里为什么不用
scss
,因为Windows
使用node-sass
,需要先安装 Microsoft Windows SDK for Windows 7 and .NET Framework 4。我怕有些人copy这份代码后,没注意,运行不起来。所以这里不用
scss
了,如果需要,自行编译哦。npm install css-loader style-loader --save-dev
css-loader
使你能够使用类似@import
和url(...)
的方法实现require()
的功能;style-loader
将所有的计算后的样式加入页面中; 二者组合在一起使你能够把样式表嵌入webpack
打包后的JS文件中。webpack.dev.config.js
rules
增加我们用
Page1
页面来测试下src/pages/Page1/Page1.css
src/pages/Page1/Page1.js
好了,现在
npm start
去看效果吧。npm install --save-dev url-loader file-loader
webpack.dev.config.js
rules
增加options limit 8192
意思是,小于等于8K的图片会被转成base64
编码,直接插入HTML中,减少HTTP
请求。我们来用
Page1
测试下给
images
文件夹放一个图片。修改代码,引用图片
src/pages/Page1/Page1.js
可以去看看效果啦。
为什么要实现按需加载?
我们现在看到,打包完后,所有页面只生成了一个
build.js
,当我们首屏加载的时候,就会很慢。因为他也下载了别的页面的js
了哦。如果每个页面都打包了自己单独的JS,在进入自己页面的时候才加载对应的js,那首屏加载就会快很多哦。
在
react-router 2.0
时代, 按需加载需要用到的最关键的一个函数,就是require.ensure()
,它是按需加载能够实现的核心。在4.0版本,官方放弃了这种处理按需加载的方式,选择了一个更加简洁的处理方式。
传送门
根据官方示例,我们开搞
npm install bundle-loader --save-dev
bundle.js
src/router/Bundle.js
src/router/router.js
现在你可以
npm start
,打开浏览器,看是不是进入新的页面,都会加载自己的JS的~但是你可能发现,名字都是
0.bundle.js
这样子的,这分不清楚是哪个页面的js
呀!我们修改下
webpack.dev.config.js
,加个chunkFilename
。chunkFilename
是除了entry
定义的入口js
之外的js
~现在你运行发现名字变成
home.js
,这样的了。棒棒哒!那么问题来了
home
是在哪里设置的?webpack
怎么知道他叫home
?其实在这里我们定义了,
router.js
里面import Home from 'bundle-loader?lazy&name=home!pages/Home/Home';
看到没。这里有个
name=home
。嘿嘿。参考地址:
想象一下这个场景~
我们网站上线了,用户第一次访问首页,下载了
home.js
,第二次访问又下载了home.js
~这肯定不行呀,所以我们一般都会做一个缓存,用户下载一次
home.js
后,第二次就不下载了。有一天,我们更新了
home.js
,但是用户不知道呀,用户还是使用本地旧的home.js
。出问题了~怎么解决?每次代码更新后,打包生成的名字不一样。比如第一次叫
home.a.js
,第二次叫home.b.js
。文档看这里
我们照着文档来
webpack.dev.config.js
每次打包都用增加
hash
~现在我们试试,是不是修改了文件,打包后相应的文件名字就变啦?
但是你可能发现了,网页打开报错了~因为你
dist/index.html
里面引用js
名字还是bundle.js
老名字啊,改成新的名字就可以啦。啊~那岂不是我每次编译打包,都得去改一下js名字?欲知后事如何,且看下节分享。
这个插件,每次会自动把js插入到你的模板
index.html
里面去。npm install html-webpack-plugin --save-dev
新建模板
index.html
src/index.html
修改
webpack.dev.config.js
,增加plugin
npm start
运行项目,看看是不是能正常访问啦。~说明一下:
npm start
打包后的文件存在内存中,你看不到的。~ 你可以把遗留dist/index.html
删除掉了。想象一下,我们的主文件,原来的
bundle.js
里面是不是包含了react
,redux
,react-router
等等这些代码??这些代码基本上不会改变的。但是,他们合并在
bundle.js
里面,每次项目发布,重新请求bundle.js
的时候,相当于重新请求了react
等这些公共库。浪费了~我们把
react
这些不会改变的公共库提取出来,用户缓存下来。从此以后,用户再也不用下载这些库了,无论是否发布项目。嘻嘻。webpack
文档给了教程,看这里webpack.dev.config.js
把
react
等库生成打包到vendor.hash.js
里面去。但是你现在可能发现编译生成的文件
app.[hash].js
和vendor.[hash].js
生成的hash
一样的,这里是个问题,因为呀,你每次修改代码,都会导致vendor.[hash].js
名字改变,那我们提取出来的意义也就没了。其实文档上写的很清楚,但是无奈,如果用
chunkhash
,会报错。和webpack-dev-server --hot
不兼容,具体看这里。现在我们在配置开发版配置文件,就向
webpack-dev-server
妥协,因为我们要用他。问题先放这里,等会我们配置正式版webpack.config.js
的时候要解决这个问题。文档看这里
我们要开始做了~
在
webpack.dev.config.js
的基础上先做以下几个修改~webpack-dev-server
相关的东西~devtool
的值改成cheap-module-source-map
hash
改成chunkhash
webpack.config.js
在
package.json
增加打包脚本"build":"webpack --config webpack.config.js"
然后执行
npm run build
~看看dist
文件夹是不是生成了我们发布要用的所有文件哦?接下来我们还是要优化正式版配置文件~
webpack
使用UglifyJSPlugin
来压缩生成的文件。npm i --save-dev uglifyjs-webpack-plugin
webpack.config.js
npm run build
发现打包文件大小减小了好多。webpack.config.js
npm run build
后发现vendor.[hash].js
又变小了。刚才我们把
[name].[hash].js
变成[name].[chunkhash].js
后,npm run build
后,发现
app.xxx.js
和vendor.xxx.js
不一样了哦。但是现在又有一个问题了。
你随便修改代码一处,例如
Home.js
,随便改变个字,你发现home.xxx.js
名字变化的同时,vendor.xxx.js
名字也变了。这不行啊。这和没拆分不是一样一样了吗?我们本意是vendor.xxx.js
名字永久不变,一直缓存在用户本地的。~
官方文档推荐了一个插件HashedModuleIdsPlugin
现在你打包,修改代码再试试,是不是名字不变啦?错了,现在打包,我发现名字还是变了,经过比对文档,我发现还要加一个
runtime
代码抽取,加上这句话就好了~为什么呢?看下解释。
注意,引入顺序在这里很重要。CommonsChunkPlugin 的 'vendor' 实例,必须在 'runtime' 实例之前引入。
想象一个场景,我们的静态文件放在了单独的静态服务器上去了,那我们打包的时候,如何让静态文件的链接定位到静态服务器呢?
看文档Public Path
webpack.config.js
output
中增加一个publicPath
,我们当前用/
,相对于当前路径,如果你要改成别的url
,就改这里就好了。你现在打开
dist
,是不是发现好多好多文件,每次打包后的文件在这里混合了?我们希望每次打包前自动清理下dist
文件。npm install clean-webpack-plugin --save-dev
webpack.config.js
现在
npm run build
试试,是不是之前的都清空了。当然我们之前的api
文件夹也被清空了,不过没关系哦~本来就是测试用的。目前我们的
css
是直接打包进js
里面的,我们希望能单独生成css
文件。我们使用extract-text-webpack-plugin来实现。
npm install --save-dev extract-text-webpack-plugin
webpack.config.js
npm run build
后发现单独生成了css
文件哦axios
和middleware
优化API请求先安装下axios
npm install --save axios
我们之前项目的一次API请求是这样写的哦~
action
创建函数是这样的。比我们现在写的fetch
简单多了。然后在dispatch(getUserInfo())后,通过
redux
中间件来处理请求逻辑。中间件的教程看这里
我们想想中间件的逻辑
dispatch
REQUEST
请求。dispatch
SUCCESS
请求,如果定义了afterSuccess()
函数,调用它。dispatch
FAIL
请求。来写一个
src/redux/middleware/promiseMiddleware.js
修改
src/redux/store.js
来应用这个中间件修改
src/redux/actions/userInfo.js
是不是简单清新很多啦?
修改
src/redux/reducers/userInfo.js
action.userInfo
修改成了action.result.data
。你看中间件,请求成功,会给action
增加一个result
字段来存储响应结果哦~不用手动传了。npm start
看看我们的网络请求是不是正常哦。使用自动编译代码时,可能会在保存文件时遇到一些问题。某些编辑器具有“安全写入”功能,可能会影响重新编译。
要在一些常见的编辑器中禁用此功能,请查看以下列表:
webpack
公共配置想象一个场景,现在我想给
webpack
增加一个css modules
依赖,你会发现,WTF?我即要修改webpack.dev.config.js
,又要修改webpack.config.js
~这肯定不行啊。所以我们要把公共的配置文件提取出来。提取到
webpack.common.config.js
里面~webpack.dev.config.js
和webpack.config.js
写自己的特殊的配置。这里我们需要用到webpack-merge来合并公共配置和单独的配置。
这样说一下,应该看代码就能看懂了。下次公共配置直接就写在
webpack.common.config.js
里面啦。npm install --save-dev webpack-merge
touch webpack.common.config.js
webpack.common.config.js
webpack.dev.config.js
webpack.config.js
现在我们优化下目录结构,把
router
和nav
分开,新建根组件App
。component
改名为components
,因为是复数。。。注意修改引用的地方哦。components/App/APP.js
components/Nav/Nav
组件,把router/router.js
里面的nav
提出来。components/Loading/Loading
组件,把router/router.js
里面的Loading
提出来。src/index.js
修改pages/NotFound/NotFound
组件。router/router.js
,增加404
先来说说babel-plugin-transform-runtime
npm install --save-dev babel-plugin-transform-runtime
再来看babel-polyfill
Q: 为什么要集成
babel-polyfill
?A:
网上很多人说,集成了
transform-runtime
就不用babel-polyfill
了,其实不然,看看官方怎么说的:所以,我们还是需要
babel-polyfill
哦。npm install --save-dev babel-polyfill
修改webpack两个配置文件。
webpack.common.config.js
webpack.dev.config.js
参考地址:
官方文档看这里
Q: 这是啥?为什么要用它?
他有很多很多的插件,我们举几个例子~
Autoprefixer这个插件,可以自动给css属性加浏览器前缀。
postcss-cssnext 允许你使用未来的 CSS 特性(包括 autoprefixer)
当然,它有很多很多的插件可以用,你可以去官网详细了解。我们今天只用
postcss-cssnext
。(它包含了autoprefixer)修改
webpack
配置文件,增加postcss-loader
webpack.dev.config.js
webpack.config.js
根目录增加
postcss
配置文件。postcss.config.js
现在你运行代码,然后写个css,去浏览器审查元素,看看,属性是不是生成了浏览器前缀?
今天突然发现,当修改reducer代码的时候,页面会整个刷新,而不是局部刷新唉。
这不行,就去查了webpack文档,果然是要配置的。看这里
代码修改起来也简单,增加一段监听reducers变化,并替换的代码。
src/redux/store.js
哦了~
每个改进都是为了解决问题。
现在我在开发中碰到了问题,我先描述下问题:
我们现在做前后端完全分离的应用,前端写前端的,后端写后端的,他们通过API接口连接。
前端同学心理路程:"后端同学接口写的好慢,我都没法调试了。"
是不是有这个问题呢?一般我们怎么解决?
第一种:自己这边随便造点数据,等后端接口写好了之后,再小修改,再调试。
第二种:想想我们之前获得用户信息的
dist/api/user.json
,我们可以用这种方式来调试。但是想象下,我们要模拟一个文章列表,就要手动写几十列。oh~no!
并且,后端接口一般都不带
.json
,到时候对接,是不是还得改代码?好了,下面介绍下今天的主角Mock.js。
他会做一件事情:拦截AJAX请求,返回需要的数据!
我们写AJAX请求的时候,正常写,Mock.js会自动拦截的。
Mock.js提供各种随机生成数据。具体可以去官网看~
下面我们就在项目中集成咯:
npm install mockjs --save-dev
新建mock文件夹
touch mock
模拟一个我们之前用到的
/api/user
接口mock/mock.js
上面代码的意思就是,拦截
/api/user
,返回随机的一个中文名字,一个20个字母的字符串。我知道你看不懂,你去看看Mock.js文档就能看懂啦!
与我们的项目连接。到目前为止,刚才定义的接口和我们的项目还没有关系。
先来做,在
src/index.js
里面增加一行代码:src/index.js
现在我们删除
dist/api
文件夹,然后修改之间的接口路径,把.json
去掉。rm -rf dist/api
src/redux/actions/userInfo.js
现在我们运行
npm start
,到获取用户信息界面,看每次获取用户信息都会变化呀?到这里还没完,我们还要配置:只有在开发坏境下,才引入
mock
,在生产坏境,不引入。跟着我做:
先给
mock
文件夹加个别名,这个我就不单独介绍了:webpack.common.config.js
webpack.dev.config.js
增加然后修改
src/index.js
刚才加的那句话为下面这样这样,就只会在
npm start
开发模式下,才会应用mock,如果你不想用,就把MOCK改成false就好了。哦了,到这里就结束了~回头缕下:
我们定义了mock,在index.js引入。
mock的工作就是,拦截AJAX请求,返回模拟数据。
参考文章:
http://www.jianshu.com/p/dd23a6547114
https://segmentfault.com/a/1190000005793320
关于什么是
CSS Modules
,我这里不介绍。可以去看阮一峰的文章CSS Modules 用法教程
修改以下几个地方:
webpack.dev.config.js
webpack.config.js
src/pages/Page1/page1.css
src/pages/Page1/Page1.js
enjoy it!
json-server和
Mock.js
一样,都是用来模拟接口数据的。json-server
功能更强大,支持分页,排序,筛选等等,具体的可以去看文档。我们用
json-server
代替之前的Mock.js
。删除
Mock.js
相关代码。一共两处,
webpack.dev.config.js
,src/index.js
npm install --save-dev json-server
写个demo,我们生成虚假数据还是用
mockjs
。mock/mock.js
package.json
json-server
服务器去。哦了,你可以
npm run mockdev
启动项目,然后访问我们之前的用户信息接口,试试啦。问题:
windows
不支持命令并行执行&
,你可以分开执行,或者使用npm-run-all1. react热模块加载无效
举例:在首页中,当我们计数加上去,然后修改代码,计数又恢复成0了。也就是热模块加载的时候,重置了
react
的state
。如果我们不使用
code splitting
,是没有这个问题的。但是我们就是要用,哼!解决问题参考这里:https://github.com/gaearon/react-hot-loader/tree/next#code-splitting
解决步骤:
npm install react-hot-loader@next
其他模块如果需要,可以自己同理修改哦。
The text was updated successfully, but these errors were encountered: