前几天做了一个项目:【node】记录项目的开始与完成——pipeline_kafka流式数据库管理项目;因为开发时间紧迫,浅略的使用了一下react,感觉这个ui库非常的符合我的口味,现在趁着有空闲时间,将项目前端重构一番。这里面存在一些坑,都是深不见底的水坑,说多了都是泪水。。。好在顺利完成,现在在这里再一步一步重来一遍,和需要学习webpack的前端童鞋分享。

准备

tips:文章最后可下载demo

一:目录

  

  首先我们要新建目录,

  

  新建app文件夹,它存放入口文件,component组件,

  新建static文件夹存放打包后的文件,

  新建webpack文件夹,存放的webpack配置文件。

二、生成package.json

  在当前目录打开cmd或者PowerShell或者终端,

  

  输入npm init 然后一直回车到执行完毕,package.json就滚到文件夹根目录下面了

、安装webpack

  shell输入 webpack i webpack --save 安装webpack

  

  我成功后的提示是这样的。

四、新建文件

  在目录app中新建main.js,

  在目录webpack中新建webpack的配置文件  webpack.config.js

  在目录static中新建一个  index.html

  在目录static中新建一个js目录

五、初步配置

  首先写一下 /static/index.html这个文件,因为生成的文件目录在 /static/js文件夹里面,所以这里要预先引用打包后的文件,最后访问这个html文件就可以看到效果

  

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title>webpack_Demo</title>
</head>
<body>
<div class="content">
</div>
<script src="./js/app.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>

  然后配置webpack.config.js:

  刚开始我们就配一个简单的入口和输出目录就可以了: 

var path = require("path");

module.exports = {
entry:{  //入口文件
"app":path.join(__dirname,"../app/main.js") //app对应生成的文件名
},
output:{
path:path.join(__dirname,"../static/js/"),
filename:"[name].js" //这里[name]就是表示对应entry对象的name,然后生成的后戳是.js
}
}

 现在我们就可以简单的测试一下,在/app/main.js中随意写一些代码 ,比如alert(1)。

  在shell中调用webpack测试,运行:

  webpack --config ./webpack/webpack.config.js

  

  成功后访问index.html,查看效果,如果报错,可能是缺少哪个依赖包,安装后重复上面步骤。

  这个时候文件目录就变成了:

   app.js就是打包后生成的文件。

  现在我们要把打包命令放在package.json里,因为每次编译都要运行那么长的命令,太痛苦了。在package.json简单的配置一个script就可以使用npm run xxx运行了,编辑package.json:

  

{
"name": "web_pack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build":"webpack --config ./webpack/webpack.config.js" //添加一个build 值是打包用到的命令
},
"author": "",
"license": "ISC",
"dependencies": {
"webpack": "^3.0.0"
}
}

现在在shell里运行 npm run build就可以编译了

到这一步,初步的配置就算是完成了,接下来配置一个webpack-dev-server,然后就可以配置react组件,生成项目了

配置webpack-dev-server

  什么是webpack-dev-server?

  它是用来监控文件的修改事件,启动它的时候,会分配一个端口,指向当前的目录,一旦目录下文件被修改,它会通知浏览器自动刷新页面,省去了不断的按f5的烦恼。

  在shell中安装,运行:

  npm i webpack-dev-server --save-dev

  安装成功后,运行:

  node_modules/.bin/webpack-dev-server --config ./webpack/webpack.config.js --port 8089 --open

  --config 是webpack配置文件目录,--port 是运行的端口号

  运行成功会在系统默认浏览器弹出一个窗口,这是一个选择文件夹的界面,我们访问static,就可以访问到index.html了:

  

  这里需要注意的一点是,你还需要将index.html中的app.js引用改成http://localhost:8089/app.js,因为webpack-dev-server加载的是虚拟文件,目录在根目录下,所以需要修改这里。  

<script src="http://localhost:8089/app.js" type="text/javascript" charset="utf-8"></script>

  项目完成后再改成对应的路径。

  修改完成,修改一下main.js中的js代码,再看看浏览器中页面是否改变。webpack-dev-server大致就配置好了,另外附上它的api地址:

  webpack-dev-server

 最后再把命令配置到package.json中

{
"name": "web_pack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "node_modules\.bin\webpack-dev-server --config ./webpack/webpack.config.js --port 8089 --open",  //添加到test中
"build":"webpack --config ./webpack/webpack.config.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"webpack": "^3.0.0"
}
}

现在运行npm start test 就可以开始开发了。

配置react

  到了这一步,我们要开始配置react,首先还是安装依赖包,编译jsx文件需要用到babel、babel-core、babel-loader、babel-preset-es2015、babel-preset-react、还有react自己的react、react-dom。安装他们:

  npm i babel babel-core babel-loader babel-preset-es2015 babel-preset-react react react-dom --save

  安装成功之后,先在main.js写一个demo

  

var React = require("react");
var ReactDOM = require("react-dom");
ReactDOM.render(
<div>
<h1>welcome</h1>
</div>
,document.querySelector(".content")
);

  这里一定要用 ReactDOM.render 老的版本react.render会报语法错误。

配置babel-loader

  在webpack.config.js添加babel-loader用来解析jsx和es6的代码:

  

var path = require("path");

module.exports = {
entry:{
"app":path.join(__dirname,"../app/main.js") //入口文件 name对应输出的[name]
},
output:{
path:path.join(__dirname,"../static/js/"), //输出路径
filename:"[name].js" //输出app.js
},
module:{
loader:[
{
test:/\.(js|jsx)$/, //这是配置加载文件的规则 值是正则表达式 这里写的意思是.js .jsx结尾的文件加载loader
loader:"babel-loader",
exclude:/node_module/, //这个目录不需要加载loader
query:{
presets:["react","es2015"] //加载loader的presets
}
}
]
}
}

  配置了module下面的loaders。

  然后npm run test 开启服务,测试一下代码是否可以运行。

  顺利的话,这里应该能看到welcome了:

  

  现在的代码结构显然过于简单,下面我们在app文件目录下新建两个目录 component 和 views。

  先在component 文件夹下新建hello.jsx,写一些代码:

import React from "react";

class Hello extends React.Component{
constructor(props){
super(props);
this.propTypes = {
text:React.PropTypes.string
}
}
render(){
return <div className="hello">
hello <span>{this.props.text}</span>
</div>
}
}
module.exports = Hello;

  一般我的import 语法用来表示react组件或其他资源的引入,require语法用来表示js的引入,另外这里用的是es6的class语法。关于es6,在文章下面有浅略说明。

  然后再views新建index.jsx,这里可以写主要的页面代码:

import React from 'react';
import Hello from "../component/hello.jsx"; //引入hello组件 class Index extends React.Component{
render(){
return <div className="index_container">
<Hello text="world"></Hello>
</div>
}
} module.exports = Index;

 最后main.js引入index,把index加入rander就可以看到效果了:

var React = require("react");
var ReactDOM = require("react-dom"); import Index from "./views/index.jsx"; //引入index
ReactDOM.render(
<div>
<Index></Index>  //插入index视图
</div>
,document.querySelector(".content")
);

查看效果:

到了这一步,基本的视图结构就完成了,接下来配置css的加载,基本和react的方式一样,加载对应的loader,解析对应的文件。

配置css:

  视图解决了,现在我们要解决css的引入问题,这里可以选择的就比较多 css、sass、less等都可以,我选择的是css,因为我的sass文件可以使用ruby的sass编译,在编辑保存时已经自动编译成css了,个人觉得这样管理起来更加方便。

  首先还是安装依赖,运行:

  npm i css-loader file-loader style-loader url-loader --save-dev

  file-loader url-loader 是用来编译图片资源的,它会将url()中的静态资源打包编译成base64格式,这里需要注意,不要在css中写找不到文件的路径,否则会报错编译失败。

  安装完成后配置css-loader:

  

var path = require("path");

module.exports = {
entry:{
"app":path.join(__dirname,"../app/main.js") //入口文件 name对应输出的[name]
},
output:{
path:path.join(__dirname,"../static/js/"), //输出路径
filename:"[name].js" //输出app.js
},
module:{
loaders:[
{
test:/\.(js|jsx)$/, //这是配置加载文件的规则 值是正则表达式 这里写的意思是.js .jsx结尾的文件加载loader
loader:"babel-loader",
exclude:/node_module/, //这个目录不需要加载loader
query:{
presets:["react","es2015"] //加载loader的presets
}
},
{
test:/\.css$/, //配置.css后戳的解析
loader:"style-loader!css-loader"
},
       {
         test:/\.(png|jpg)$/, //配置静态文件解析
         loader:"url-loader?limit=8192"
       }
]
}
}

注意style-loader必须写在css-loader前面,否则就会报错

  配置完成,在hello.jsx引入个css瞧瞧(这里要重启一下test):

  

引入的方法是

import "./hello.css";

引入成功,这样css就可以使用了

项目结构

  到目前为止 项目的结构是这样的:

  

  app中存放 组件(component)、视图(views)、入口文件 。

  static中存放打包后的项目文件。

  webpack中存放webpack的配置文件

  建议将公共组件打包,比如建一个hello文件夹,里面存放hello.jsx和hello.css以及需要的插件、文档,这样它的多项目复用将变得非常方便,拷贝文件即可。

浅谈es6以及react中的小坑

  es6的class关键字看起来很性感,实际上也只是整了个容,感觉内在变化不多。与createClass差别不是很大,在react中每次生命组件都要继承React.Component。

  比如上面的hello.jsx:

constructor(props){
super(props);
this.propTypes = {
text:React.PropTypes.string
}
}

  这是构造函数,就是new xxx()调用的那个函数,这里为啥要super? 这是个奇怪的写法,原因是因为构造函数中访问不到this,需要调用super()才能顺利访问到this,这里个人尤为不解,虽然理解起来也不难,构造函数属于static方法,这里为啥不能和java一样的逻辑,构造函数只能访问类?

   this.propTypes  

   这个属性标明了组件中所有用到的props 并且能验证传入的值的正确性,感觉组件有它非常有必要,建议写props不要少了这个属性。

 react 中this的坑

  在hello.jsx组件上添加一个click事件,在事件中打印this:

class Hello extends React.Component{
constructor(props){
super(props);
this.propTypes = {
text:React.PropTypes.string
}
}
render(){
return <div className="hello" onClick={this.print}>
hello <span>{this.props.text}</span>
</div>
}
print(){
console.log("点击事件");
console.log(this);
}
}

   会发现this的值既不是点击dom也不是class而是null:

  

  可是如果在静态文件中写React.createClass则不会出现null。

  我的解决办法是在render中强制指定this为class: 

render(){
this.print = this.print.bind(this);//绑定this到函数
return <div className="hello" onClick={this.print}>
hello <span>{this.props.text}</span>
</div>
}

查看官方文档解释是:

  React.createClass有一个内置的魔术功能,可以自动绑定所有方法this。这对于在其他类中不用于此功能的JavaScript开发人员来说可能会有点混乱,或者当从React转到其他类时可能会令人困惑。因此,我们决定不将此内置到React的类模型中。如果需要,您仍然可以在构造函数中明确地预处理方法。
 
在遇到点击更改state时,一定会用到this。要注意this的指向问题

总结

  前端就像是一只正当壮年的母鸡,今天下个蛋,明天下个蛋,是寡蛋是好蛋不知道,今天的蛋和明天的蛋尝起来味道也差不多。我们就像是饲养员,负责给母鸡送吃的,下了蛋就要马上负责收,否则要么就烂了、要么就孵出小鸡吃不了鸡蛋了。

  那些层出不穷的框架,坏掉的框架、已经变的强大就很难驾驭的框架,这对前端来说是一个考验。

相关资源

  下载我最终做好的demo

  react文档翻译(快速入门)

  
转载请注明出处(完)

一步一步使用webpack+react+scss脚手架重构项目的更多相关文章

  1. 【前端】一步一步使用webpack+react+scss脚手架重构项目

    前言 前几天做了一个项目:[node]记录项目的开始与完成——pipeline_kafka流式数据库管理项目:因为开发时间紧迫,浅略的使用了一下react,感觉这个ui库非常的符合我的口味,现在趁着有 ...

  2. react官方脚手架搭建项目

    1.全局安装 npm install -g create-react-app 2. app后面还要给项目文件命名 create-react-app //是全局命令来创建react项目 3.然后按照提示 ...

  3. 一步一步建立 webpack 4 项目

    一步一步建立 webpack 4 项目 cnpm init -y cnpm i webpack --save-dev cnpm i webpack-cli --save-dev 修改 package. ...

  4. webpack多页应用架构系列(一):一步一步解决架构痛点

    这系列文章讲什么? 前些时间,写过一个项目,前后端分离,没有借助任何框架,项目页面特别的多,页面都是html直接写的,许多公共html,写了好多处,有一个地方需要改就得改好多地方,js也是随意写,每个 ...

  5. webpack+react+antd 单页面应用实例

    React框架已经火了好长一段时间了,再不学就out了! 对React还没有了解的同学可以看看我之前的一篇文章,可以快速简单的认识一下React.React入门最好的实例-TodoList 自己从开始 ...

  6. 使用 webpack + react + redux + es6 开发组件化前端项目

    因为最近在工作中尝试了 webpack.react.redux.es6 技术栈,所以总结出了一套 boilerplate,以便下次做项目时可以快速开始,并进行持续优化.对应的项目地址:webpack- ...

  7. webpack+react+es6开发模式

    一.前言 实习了两个月,把在公司用到的前端开发模式做个简单的整理.公司里前端开发模式webpack+react+redux+es6,这里去掉了redux. webpack, react, redux等 ...

  8. webpack react基础配置一

    简单介绍webpack react基本配置,入门型: 环境配置: 依赖nodejs,官网下载最新版的nodejs:nodejs.org/en 安装完nodejs  npm便自动集成了,通过npm安装其 ...

  9. 手把手教你如何使用webpack+react

    上一篇随笔讲述了新手入门入门前端 里面提到的第四阶段跟上当前前端的发展需要入门一个框架和自动化工具,当时推荐的是webpack+react 今天正好有空,也把自己入门webpack + react 的 ...

随机推荐

  1. Keepalived 主备配置

    keepalived主备或多主多备,配置都是一样配置方法,只是搭建多少的问题. 1.keepalived安装 参考:https://www.cnblogs.com/zwcry/p/9542867.ht ...

  2. OpenSSL for Android

    http://blog.csdn.net/xiongmc/article/details/25736041 OpenSSL1)开源项目Guardian Project试图让Android手机也拥有类似 ...

  3. new Date(dateString)

    xxxx-xx-xx xx:xx:xx chrome firefox opera xxxx/xx/xx xx:xx:xx chrome firefox opera safari ios(苹果手机只认此 ...

  4. 2018.7.12训练赛 -K

    水题 判断素数 因为范围是到16位,所以可以用long long存储 然后判断是否为素数就ok了. 但我提交之后显示10个测试样例通过了9个.......原因是下面标红的部分. 埃氏筛法:若a是合数, ...

  5. 谈谈 cci 与 i2c

    cci的名字叫, camera control interface, 他由两部分组成,一是i2c ,而另一个部分是 gpio.也就是说,cci 包含i2c.一般情况下,我们只是用到了i2c 部分,没有 ...

  6. 算法总结之 数组的partition调整

    给定一个有序数组arr, 调整arr使得这个数组的左半部分没有重复元素且升序,而且不用保证右边是否有序 分区就ok了 u区是 无重复且升序的  u是这个区域的最后位置,初始u=0 i做从左到右的遍历, ...

  7. 【bzoj4401】块的计数(水dfs)

    题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4401 假设把树划分为x个节点作一块,那么显然只有当x|n的时候才可能存在划分方案,并且这 ...

  8. 基于docker环境,搭建 jetty环境, 部署java项目

    前提: 1.Ubuntu 系统. 2.docker环境已经安装好. 实现步骤: 1.上docker hub 下载jetty docker 镜像. 执行命令:$ sudo docker pull jet ...

  9. CreateThread创建线程传递结构体参数

    #include "stdafx.h" #include <stdio.h> #include <windows.h> #include <stdli ...

  10. 关于选中的磁盘具有MBR分区表。在EFI系统上,Windows只能安装到GPT磁盘。问题解决

    昨天在为一位学弟装系统的时候需要了这个问题,现在把解决问题的步骤写下来. 在此界面按shift+F10 启动cmd命令行模式 在cmd模式中输入diskpart,进入diskpart模式 此时,lis ...