【前端】一步一步使用webpack+react+scss脚手架重构项目
前言
前几天做了一个项目:【node】记录项目的开始与完成——pipeline_kafka流式数据库管理项目;因为开发时间紧迫,浅略的使用了一下react,感觉这个ui库非常的符合我的口味,现在趁着有空闲时间,将项目前端重构一番。这里面存在一些坑,都是深不见底的水坑,说多了都是泪水。。。好在顺利完成,现在在这里再一步一步重来一遍,和需要学习webpack的前端童鞋分享。
准备
tips:文章最后可下载demo
一:目录
首先我们要新建目录,
新建app文件夹,它存放入口文件,component组件,
新建static文件夹存放打包后的文件,
新建webpack文件夹,存放的webpack配置文件。
二、生成package.json
在当前目录打开cmd或者PowerShell或者终端,
输入npm init 然后一直回车到执行完毕,package.json就滚到文件夹根目录下面了
三、安装webpack
shell输入 npm i webpack -g 安装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 run 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结尾的文件加载loaderloader:"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结尾的文件加载loaderloader:"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>}
查看官方文档解释是:
总结
前端就像是一只正当壮年的母鸡,今天下个蛋,明天下个蛋,是寡蛋是好蛋不知道,今天的蛋和明天的蛋尝起来味道也差不多。我们就像是饲养员,负责给母鸡送吃的,下了蛋就要马上负责收,否则要么就烂了、要么就孵出小鸡吃不了鸡蛋了。
那些层出不穷的框架,坏掉的框架、已经变的强大就很难驾驭的框架,这对前端来说是一个考验。
相关资源
下载我最终做好的demo
react文档翻译(快速入门)
转载于:https://www.cnblogs.com/ztfjs/p/webpack.html
【前端】一步一步使用webpack+react+scss脚手架重构项目相关推荐
- 手挽手带你学React:四档(上)一步一步学会react-redux (自己写个Redux)
手挽手带你学React入门四档,用人话教你react-redux,理解redux架构,以及运用在react中.学完这一章,你就可以开始自己的react项目了. 之前在思否看到过某个大神的redux搭建 ...
- webpack+react+es6开发模式
一.前言 实习了两个月,把在公司用到的前端开发模式做个简单的整理.公司里前端开发模式webpack+react+redux+es6,这里去掉了redux. webpack, react, redux等 ...
- 从零开始一个webpack+react项目
从零开始一个webpack+react项目 最近在做react组件化的分享,从项目中抽离组件,那么第一步自然是搭建相关的环境 本篇旨在从零开始,用最少的配置.最少的代码.最少的依赖来搭建一个最简单的w ...
- 基于 Webpack 3 的 React 工程项目脚手架
基于 Webpack 3 的 React 工程项目脚手架从属于笔者的 Web 前端入门与工程实践,算来已经是笔者 React 技术栈脚手架的第四个迭代版本.更多关于 React 或者前端开发相关的资料 ...
- SpringBoot+MyBatisPlus+ElementUI一步一步搭建前后端分离的项目(附代码下载)
场景 一步一步教你在IEDA中快速搭建SpringBoot项目: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/87688277 ...
- button active 跳转到另一个页面_一步一步实现一个古诗词网站(四)——首页
汪小黑:一步一步实现一个古诗词网站(三)--首页zhuanlan.zhihu.com 在上篇文章中,我们一步一步的实现了我们的静态首页,从中学习到了页面布局方面的知识. 在这篇文章中,我们将使用 J ...
- 【Linux】一步一步学Linux——dpkg-preconfigure命令(275)
00. 目录 文章目录 00. 目录 01. 命令概述 02. 命令格式 03. 常用选项 04. 参考示例 05. 附录 01. 命令概述 dpkg-preconfigure命令用于在Debian ...
- 【Linux】一步一步学Linux——dpkg-reconfigure命令(272)
00. 目录 文章目录 00. 目录 01. 命令概述 02. 命令格式 03. 常用选项 04. 参考示例 05. 附录 01. 命令概述 dpkg-reconfigure命令是Debian lin ...
- 【Linux】一步一步学Linux——indent命令(262)
00. 目录 文章目录 00. 目录 01. 命令概述 02. 命令格式 03. 常用选项 04. 参考示例 05. 附录 01. 命令概述 indent命令可识别C语言代码文件,并加以格式化,以方便 ...
- 【Linux】一步一步学Linux——gcc命令(249)
00. 目录 文章目录 00. 目录 01. 命令概述 02. 命令格式 03. 常用选项 04. 参考示例 05. 附录 01. 命令概述 gcc命令使用GNU推出的基于C/C++的编译器,是开放源 ...
最新文章
- Hinton等人新研究:如何更好地测量神经网络表示相似性
- Google联手Facebook 要在AI研究上搞什么大事?
- android浮动文本,android – 如何将文本添加到浮动操作按钮?
- Python学习笔记:偏函数
- mysql myisam存储引擎不能添加外键,添加后显示成功,实则失败
- mac os mysql 命令_Mac环境下MySQL的安装和基本命令的使用
- C++ share_prt 简单设计和实现
- pcie 的function_PCIe扫盲——BDF与配置空间
- [开发技巧3]不显示报表直接打印
- 扩展吉日嘎拉的用户角色管理,让用户角色编码和名称在一个组织里面唯一
- JeeWx捷微管家系统
- 让AngularJS兼容IE8及其以下浏览器版本的方法
- 非线性方程的数值解法:二分法的MATLAB实现
- nanomsg的协议
- Cypress使用教程
- 霍志刚中国科学院计算机,曙光4000系列高性能计算机研究集体
- 使用JDBC的基本步骤
- 可以降低汽车气缸里面的机油由于摩擦产生的蓝烟的机油添加剂
- AspectJ简单实现
- linux的LCD的驱动编写
热门文章
- Windows消息前缀
- CSS图片文字排版01
- 日志:实现微信公众号自动问答机器人(待整理)
- yaahp使用教程_结合层次分析法和模糊综合评价法的评价方法-利用yaahp
- wps页眉怎么设置不同页码_wps页眉的页码和页脚的页码不同怎么设置?
- quartz 每月一次_Quartz 每月1号,执行规则表达式怎么列?
- 计算机组成原理实验二八位寄存器,计算机组成原理课后参考答案
- Hadoop单机版安装
- 光纤通道交换机的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
- RV32G下lui/auipc和addi结合加载立即数时的补值问题