小菜鸟之零基础入门webpack+React+ES6环境配置

前言

刚入职场,大学做外包常用的jQuery+bootstrap已经无法满足需求,坐在井里并且技术能够满足业务需求的时候总是难以推动技术革新的,加上自己的学习自驱力也不够,于是现在需要在短时间内上手webpack+react+ES6的项目环境。
大学期间也不是没有尝试过跳出舒适圈学习新框架,但是都因为思绪混乱退下了总之因为各种原因没有坚持学下去,下图差不多就是当时的我本人叭:

T_T对不起是真的很凌乱

基本概念

既然是零基础入门,首先当然得搞清这么多工具之间的关系,其实单单学习react、vue等框架是不难的,菜鸟教程上的文章我相信只要有些编程基础的都能看懂,难的就是和这些工具混合使用,往往都是这个过程的学习成本比较高。上图提到的这些其实就是前端现在的生态圈,近些年前端工作量不断提升,框架层出不穷,工程化解决方案也越来越多。下面来谈一下以我目前的基础对上图提到react,npm,webpack,node等之间的关系。

  1. nodeJS
    node.js是javascript的一种运行环境,是一款编写服务器端JavaScript的工具,也是一个平台,你可能会有这不是服务端的东西吗的疑惑,但是因为你接下来要用到的很多工具都基于他,所以你需要安装Node.js,即使你不会把它用于服务器端开发。
  2. npm
    npm是包管理器,可以类比成一个前端插件商店,会帮你把项目依赖的插件包都帮你加入购物车供你统一下载,有大神总结过

在Node.js上开发时,会用到很多别人已经写好的javascript代码,如果每当我们需要别人的代码时,都根据名字搜索一下,下载源码,解压,再使用,会非常麻烦。于是就出现了包管理器npm。大家把自己写好的源码上传到npm官网上,如果要用某个或某些个,直接通过npm安装就可以了,不用管那个源码在哪里。并且如果我们要使用模块A,而模块A又依赖模块B,模块B又依赖模块C和D,此时npm会根据依赖关系,把所有依赖的包都下载下来并且管理起来。

  1. webpack,grunt
    webpack,grunt是前端工程化的工具,可以帮助前端完成混淆压缩,校验等工作。它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(如Scss、Less等CSS预处理器,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。这些扩展语言虽然大大的提高了我们的开发效率,但是利用它们开发的文件往往需要进行额外的处理才能让浏览器识别,而手动处理却是非常繁琐的。webpack还会管理依赖和模块导入。
  2. react
    React是我们使用的框架,它让我们可以更轻松地创建交互式站点。你描述UI,React会为你渲染并处理DOM操作。(但要完整的开发一个项目仅仅靠react是不够的,首先React-Router是必不可少的,接着要考虑怎么存取数据可能还需要了解一下Redux,可以先忽略,后面再来看
  3. ES6
    ES6是js的语言标准,这个很好理解,相对于ES5,ES6拥有一些新特性可以更轻松的让你用js实现一些功能。另外,由于ES6新的语言特性,使组件化开发显得更加直观,也更适合配合react来完成项目开发。

以上是我目前的理解,如果你还是没有搞清楚这些概念也没有关系,建议你先动手开始写,这些概念的东西会在你心里逐渐明晰,我也相信自己会对这些概念随着项目经验的增长有更深层次的理解。

好惹接下来开始正式学习

1.安装Git并关联webstorm把公司的项目拉下来

虽然之前接触过Git但是只懂皮毛,在公司的新电脑上重新安装的时候还是出现了不少问题,这里基本参考了这个教程:Git+Webstorm配置
我跳过了手动映射路径这一步,以及补充一点,如果采用ssh方式拉取项目的话要在对应的代码仓上添加刚刚过程中生成的ssh公钥。
最后在webstorm上拉取项目时提醒我密码错误,我验证了无数遍我gitlab的密码发现并没有错,最后求助老大发现是win10的锅,第一次输错密码后,系统自动保存了错误密码,在凭据管理器中编辑后再拉取就没有问题了!

控制面板>凭据管理器>windows凭据

这个时候发现自己虽然能看懂业务代码逻辑,但是几乎完全不理解项目结构,所以暂且抛开已有的项目,自己试着构建一个新项目

2.ES6入门

要学react就要学习ES6的新特性方便我理解代码,但是ES6那么多新特性总不能全学完,还是先遵循二八原则
参考文章:
ES6这些就够了
ES6核心特性(一)
ES6核心特性(二)
这里补充几点:
1.类
类的基本用法:ES6 类(Class)基本用法和静态属性+方法详解

关于super关键字:ES6 的 super 到底是什么?

super(…) 做的事情就是生成一个 this。因为在原型继承中,如果一个类要继承自另一个类,那就得先实例化一次它的父类作为作为子类的原型。如果不做这件事,子类的原型就不能确定,当然也就无法创建 this。所以如果在 constructor 中没有 super(…) 就企图获取 this 就会报错。

2.导入导出
# 你真的搞懂ES6模块的导入导出规则了吗

基本使用总结:

1.当用export default people导出时,就用 import people 导入(不带大括号)
2.一个文件里,有且只能有一个export default。但可以有多个export。
3.当用export name 时,就用import { name }导入(记得带上大括号)
4.当一个文件里,既有一个export default people, 又有多个export name 或者 export age时,导入就用 import people, { name, age }
5.当一个文件里出现n多个 export 导出很多模块,导入时除了一个一个导入,也可以用import * as example

3.promise

Promise的使用流程

  • new Promise一个实例,而且要 return
  • new Promise 时要传入函数,函数有resolve reject 两个参数
  • 成功时执行 resolve,失败时执行reject
  • then 监听结果
function loadImg(src){
   const promise=new Promise(function(resolve,reject){
     var img=document.createElement('img')
     img.onload=function(){
        resolve(img)
   }
     img.onerror=function(){
        reject()
   }
    img.src=src
 })
  return promise//返回一个promise实例
}
var src="http://www.imooc.com/static/img/index/logo_new.png"
var result=loadImg(src)
result.then(function(img){
    console.log(img.width)//resolved(成功)时候的回调函数
},function(){
    console.log(“failed“)//rejected(失败)时候的回调函数
})
result.then(function(img){
    console.log(img.height)
})

promise会让代码变得更容易维护,像写同步代码一样写异步代码,同时业务逻辑也更易懂。

3.webpack入门

入门 Webpack,看这篇就够了
按教程执行
node_modules/.bin/webpack app/main.js public/bundle.js时先报错

'node_modules' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

是由于我用的win系统,记得把命令行中的’/‘替换成’\‘
解决后又报错

ERROR in multi ./app/main.js public/bundle.js
Module not found: Error: Can't resolve 'public\bundle.js' in 'E:\projects\studyNew'
 @ multi ./app/main.js public/bundle.js

解决方法

you need bundle.js as output so try instead this command
webpack app.js -o bundle.js

当然也要转换成非全局安装模式的webpack命令node_modules\.bin\webpack app\main.js -o public\bundle.js
结果运行时浏览器报错Uncaught ReferenceError: documemount is not defined

解决方法

更改文件bundle.js中documemount为document

后成功看见“Hi there and greetings!”呜呜呜呜,此处查不到任何资料为什么会这样,待考察!(原因查明。。是因为在main.js源文件中就敲错了所以打包后自然是错的我自罚一杯优酸乳。。。

另外,此处我尝试用import "./config.json"代替require,报错Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>'

var config = require('./config.json');

module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = config.greetText;
  return greet;
};

点开错误的文件,标注错误的地方是这样的一段代码:

import {normalTime} from './timeFormat';

module.exports={
  normalTime
};

原因是:The code above is ok. You can mix require and export. You can‘t mix import and module.exports.

翻译过来就是说,代码没问题,在webpack打包的时候,可以在js文件中混用require和export。但是不能混用import 以及module.exports。

因为webpack 2中不允许混用import和module.exports,解决办法就是统一改成ES6的方式编写即可。

现在的项目结构如下:


项目结构

但是npm run dev运行项目的时候又遇到报错

events.js:182
throw er; // Unhandled 'error' event
^
Error: listen EADDRINUSE 127.0.0.1:8000
at Object.exports._errnoException (util.js:1024:11)
at exports._exceptionWithHostPort (util.js:1047:20)
at Server.setupListenHandle [as _listen2] (net.js:1319:14)
at listenInCluster (net.js:1367:12)

得知是端口被占用,自然就要去查出是什么进程占用了并kill掉,具体解决方法:

例如查询80xx端口
netstat -nao | findstr “80xx”
TCP 127.0.0.1:9010 0.0.0.0:0 LISTENING 3017
你看到是PID为3017的进程占用了8080端口,如果进一步你想知道它的进程名称,你可以使用如下命令:tasklist | findstr "3017"如果你想杀死这个进程,你当然可以用前面描述的那种方法,
在任务管理器里把它KILL了,但如果你喜欢高效一点,那么用taskkill命令taskkill /pid 3017 /F就可以了。

OK这样就完成了一个webpack+react+ES6项目的基本环境配置。现在重新回去看项目,发现也基本可以理解项目结构了,例如一些配置文件是拿来干什么的,为什么会存在在那个位置。

4.开始写业务代码

看懂项目结构之后,先把项目运行起来,再边写边调试自己部分的页面,结果项目运行起来以后,请求登陆,浏览器又报错了!!!(是真的绝望!)如下:

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource

解决方法:chrome浏览器的跨域设置这个说的很清楚了,至于为什么会报错,看这里关于跨域,以及跨域的几种方式

现在基本就可以开始着手写业务代码了,react的语法不用特意去学,了解一下生命周期,写几个组件就明白了。项目还用了ant design,这个也比较简单,官网有完善的API,只要会写基础的react代码就会用了,顶多是属性配置的问题(还是要多看API)。

结语

不得不说,如果之前对这些都没怎么接触,那么想要写一个完整的webpack+react+ES6项目Demo时间成本还是挺高的。至少不像以前jQuery那样在页面引入几个js、css然后直接开撸那么简单。如果你能把提到的每个教程详细的看完一定会有不少收获,也会了解更多的东西,例如Babel、ESLint、yarn、热加载等等。

快去学习叭。。真的就分分钟跟不上时代的脚步了呜呜呜……

推荐阅读更多精彩内容