使用webpack轻松构建你的第一个react开发框架

react的路很长,这将是一个开始。

开始.jpg

开发之前,你需要首先了解一下几点:

webpack:

Webpack 是当下最热门的前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。通过 loader 的转换,任何形式的资源都可以视作模块,比如 CommonJs 模块、 AMD 模块、 ES6 模块、CSS、图片、 JSON、Coffeescript、 LESS 等。

webpack-dev-server:

在webpack中有一个在开发时很好用的功能,热加载(Hot-replace),在react开发中,结合上react-hot-loader插件,开发工作将会变得更棒:更改代码之后,你甚至都不需要去刷新你的浏览器,界面就会自动刷新。但是,要使用这一功能的话,我们就需要使用webpack-dev-server。webpack-dev-server是一个小型的node.js Express服务器,它使用webpack-dev-middleware中间件来为通过webpack打包生成的资源文件提供Web服务。它还有一个通过Socket.IO连接着webpack-dev-server服务器的小型运行时程序。webpack-dev-server发送关于编译状态的消息到客户端,客户端根据消息作出响应。

react-router:

在react开发中,react-router是由官方维护的,唯一可选的路由库。它通过管理 URL,实现组件的切换和状态的变化,开发复杂的应用几乎肯定会用到。

babel:

Babel是一个JavaScript编译器。默认情况下,babel自带了一组ES2015语法转化器。这些转化器可以让你现在就使用最新的JavaScript语法,而不需要等待浏览器提供支持。本文要讲的开发例子中,就使用到了ES6以及部分ES7所提出的一些新规范,所以需要使用babel来进行转化。

一、配置package.json文件

首先建立项目文件夹,在该项目文件夹目录下执行npm init命令,然后一直回车到底,生成package.json文件,接下来再进行详细的配置。

package.json
{
  "name": "webpack-react",
  "version": "1.0.0",
  "description": " webpack-react ",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server --hot --progress --colors",
    "build": "webpack --progress --colors"
  },
  "author": "CainZK",
  "license": "ISC",
  "devDependencies": {
    "babel": "^6.5.2",
    "babel-core": "^6.7.2",
    "babel-loader": "^6.2.4",
    "babel-plugin-react-transform": "^2.0.2",
    "babel-plugin-transform-class-properties": "^6.16.0",
    "babel-preset-es2015": "^6.6.0",
    "babel-preset-react": "^6.5.0",
    "babel-preset-stage-2": "^6.17.0",
    "classnames": "^2.2.5",
    "css-loader": "^0.23.1",
    "file-loader": "^0.8.5",
    "html-webpack-plugin": "^2.10.0",
    "react": "^0.14.8",
    "react-dom": "^15.3.2",
    "react-hot-loader": "^1.3.0",
    "react-router": "^2.8.1",
    "react-slick": "^0.14.5",
    "react-transform-hmr": "^1.0.4",
    "rmc-list-view": "^0.6.2",
    "sass-loader": "^3.2.0",
    "style-loader": "^0.13.0",
    "url-loader": "^0.5.7",
    "webpack": "^1.12.14",
    "webpack-dev-server": "^1.14.1"
  }
}

这里需要说一下scripts字段以及devDependencies字段。在scripts字段下第一个命令"start": "webpack-dev-server --hot --progress --colors"表示执行npm start命令时,会执行后面的命令,即用webpack-dev-server启动服务, --hot表示热替换配置,--progress表示显示进度,--colors表示配置输出的颜色。第二个命令build表示执行npm run build的时候,会使用webpack进行打包操作。

二、配置webpack.config.js文件

上一步打包的时候,所有的配置工作都是在webpack.config.js文件中进行的。所以接下来我们来完善webpack的相关配置。

webpack.config.js
var path = require('path');
var webpack = require('webpack');
var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, 'app');
var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
// var htmlWebpackPlugin =  require('html-webpack-plugin');

module.exports = {
  entry: {
    a:[
      'webpack/hot/only-dev-server',
      "./app/index.js"
    ],
    b:[
      'webpack/hot/only-dev-server',
      "./app/index2.js"
    ]
  },
  output: {
      path: BUILD_PATH,
      publicPath: "/build/", 
      filename: "[name].bundle.js"
  },
  module: {
      loaders: [  
          {
            test: /\.js$/, 
            exclude: /node_modules/, 
            loader: "babel-loader", 
            query:
              {
                presets:['react','es2015','stage-2'] // babel配置:添加这三个presets用来处理js和jsx
              }
          }, {
              test: /\.css$/,
              loaders: ['style', 'css', 'sass'], //.scss 文件使用 style-loader、css-loader 和 sass-loader 来编译处理
              include: APP_PATH
          }, {
              test: /\.(png|jpg)$/,
              loader: 'url?limit=40000'  //图片文件使用 url-loader 来处理,小于40000字节的直接转为base64
          }
      ]
  },
  resolve:{
      extensions:['','.js','.json']   //自动扩展文件后缀名,意味着我们require模块可以省略不写后缀名
  },
  devServer: {
      hot: true,  //热加载模式
      inline: true //inline模式(将webpack-dev-sever的客户端入口添加到包(bundle)中)
  },
  plugins: [
    new webpack.NoErrorsPlugin(),//用来跳过编译时出错的代码并记录,使编译后运行时的包不会发生错误
    new webpack.HotModuleReplacementPlugin()//全局开启代码热替换
  ]
};

entry:入口配置,这里我进行的是多页面入口文件的配置,如果是单页面的话可以这样来进行配置:

entry: {
      'webpack/hot/only-dev-server',
      "./app/index.js"
  },

path是webpack输出地址,取绝对路径;
publicPath是webpack-dev-server启动服务时在内存中文件生成的地址。
filename:这里多页面入口文件配置需要加上[name]。
loaders:使用loader对一些文件进行相应的处理。
test:使用正则匹配要处理的文件。
exclude:排除不处理的目录。
loader:要使用的loader。
...(其余相关配置已写在代码注释中)

三、完善入口页面

在项目根目录下简历index.html以及index1.html表示两个入口页面。

index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link rel="stylesheet" type="text/css" href="./app/css/base.css">
    <title>React App</title>
  </head>
  <body>
    <div id="content"></div>
    <script src="./build/b.bundle.js"></script>
  </body>
</html>

index1.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
  <div id="content"></div>
  <script src="./build/a.bundle.js"></script>
</body>
</html>

在根目录下新建app目录,新建index.js以及index1.js文件。

index.js
import React from 'react';
import ReactDOM from 'react-dom';
import myBt from './example/myBt';
import Carousel from './example/myCarousel';
import ActionSheet from './example/myActionSheet';
import { Router, Route, IndexRoute, hashHistory} from 'react-router';
import rt from './example/route';

class App extends React.Component {
    render () {
      console.log(window.screen.height);
        return (
          <div>
          {this.props.children}
          </div>
        );
    }
}

ReactDOM.render((
  <Router history={hashHistory}>
        <Route path="/" component={App} >
            <IndexRoute component={rt}/>
            <Route path="/carousel" component={Carousel}/>
            <Route path="/button" component={myBt}/>
            <Route path="/actionSheet" component={ActionSheet}/>
        </Route>
  </Router>),
  document.getElementById('content')
);
index1.js
import React from 'react';
import ReactDOM from 'react-dom';
import ListView from 'rmc-list-view';

var REQUEST_URL = 'https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json';
class App extends React.Component {
  constructor(props) {
  super(props);
  var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    this.state = {
      dataSource: ds,
      loaded:false,
    };
  }
  componentDidMount() {
    fetch(REQUEST_URL)
      .then((response) => response.json())
      .then((responseData) => {
        this.setState({
          dataSource: this.state.dataSource.cloneWithRows(responseData.movies),
          loaded: true,
        });
      })
  }
  renderLoadingView() {
    return (
        <div>
          Loading ...
        </div>
    );
  }
  render() {
    if (!this.state.loaded) {
      return this.renderLoadingView();
    }
    var rowStyle = {
      flex: 1,
      flexDirection: 'row',
      justifyContent: 'center',
      alignItems: 'center',
      backgroundColor: '#F5FCFF'
    }
    var imgStyle = {
      height:120,
      width:80
    }
    return(
      <ListView
        style={{ height: 667, backgroundColor:'#FAFAFA' }}
        dataSource={this.state.dataSource}
        renderRow={(rowData) => (
          <div style={rowStyle}>
            <img src={rowData.posters.thumbnail} style={imgStyle}/>
            <a style={{flex: 1,marginTop:15,marginLeft:10,fontSize:18,height:36,position:'absolute'}}>
              {rowData.title}
            </a>
          </div>
        )}
      />
    );
  }
};

ReactDOM.render(<App/>, document.getElementById('content'));

这里我们在index.js文件中使用了react-router,简单介绍一下它的一些配置及简单的用法。
导入路由:

import { Router, Route, IndexRoute, hashHistory} from 'react-router';

配置路由信息:

<Router history={hashHistory}>
     <Route path="/" component={App} >
          <IndexRoute component={rt}/>
          <Route path="/carousel" component={Carousel}/>
          <Route path="/button" component={myBt}/>
          <Route path="/actionSheet" component={ActionSheet}/>
     </Route>
</Router>

路由跳转页面设置:

import React from 'react';

export default class Button extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div style={{padding:20}}>
        <a href="#carousel" style={{marginLeft:20}}>
          carousel
        </a>
        <a href="#button" style={{marginLeft:20}}>
          button
        </a>
        <a href="#actionSheet" style={{marginLeft:20}}>
          actionSheet
        </a>
      </div>
    );
  }
};

path是跳转路径,component中的是跳转路径过后要展示出来的react组件。具体的详细用法可以参考npm官网的介绍,这里就不多说了。

到这里框架搭建基本完成,缺的只有文中所引用的第三方组件了,如果您感兴趣的话,可以参考github,将项目down下来,再进行研究,我也会继续完善这个简单的框架,添加更多的组件进去,方便开发。

成功搭建后的演示:


Image
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 无意中看到zhangwnag大佬分享的webpack教程感觉受益匪浅,特此分享以备自己日后查看,也希望更多的人看到...
    小小字符阅读 8,134评论 7 35
  • GitChat技术杂谈 前言 本文较长,为了节省你的阅读时间,在文前列写作思路如下: 什么是 webpack,它要...
    萧玄辞阅读 12,669评论 7 110
  • 构建一个小项目——FlyBird,学习webpack和react。(本文成文于2017/2/25) 从webpac...
    布蕾布蕾阅读 16,797评论 31 98
  • 前言 WebPack 是什么? WebPack 是什么,WebPack 可以看做是模块打包机:它做的事情是,分析你...
    Promise__阅读 1,118评论 3 12
  • 根据本人的教学经验,“创设提问”是一种有效的阅读教学方式,所谓“创设提问”就是通过提出一些创新性、可操作性、引导性...
    林夕眠阅读 178评论 0 0