ES6 + Express + Babel + Gulp + React + Webpack

自己动手才发现原来写篇好文章真的是太难了,如果评个等级的话,这篇文章大概是渣渣水平,哈哈。
不过,总算是写完了,也算是最近学习的一个总结吧 :)

本文目录

<a id="prepare">

准备工作

作为一个noder,开始一切之前当然少不了npm init
关于express, babel, gulp, webpack, react本文不进行介绍,如有需要可以到其主页自行了解。
Express
Babel
Gulp
React
Webpack

<a id="toc">

项目目录结构

app
├─ lib/
├─ public/
│  ├─ dist/
│  └─ src/
│      └─ index.js
├─ src/
│  └─ app.js
├─ .babelrc
├─ index.html
├─ gulpfile.babel.js
├─ package.json
├─ README.md
└─ webpack.config.js

<a id="express">

Express

<a id="express-install">

安装

这次准备纯手写,所以不用express-generator生成了,简单的示例尽量不使用多余的中间件。
npm install --save express body-parser

<a id="express-server">

写个server测试一下

// src/app.js

var express = require('express');
var bodyParser = require('body-parser');

var app = express();
var router = express.Router();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());

router.get('/', function(req, res, next) {
  res.end('Hello World!');
});

app.use('/', router);

app.listen(3000, function() {
  console.log('server listening at port 3000...');
});

简单起见,404和error handler就不写了。
node src/app.js跑起来,浏览器打开http://localhost:3000,可以看到页面中显示Hello World!了。

<a id="babel">

Babel

babel升级到6.x之后,需要明确指定转换,我们使用预设的es2015。

<a id="babel-install">

安装

npm install -g babel-core
npm install --save-dev babel-core babel-preset-es2015

<a id="babelrc">

配置.babelrc

在根目录新建.babelrc文件,配置如下:

{
  "presets": ["es2015"]
}

<a id="babel-es6">

使用es6语法编写代码

我们现在将之前写过的src/app.js修改为es6语法

// src/app.js

import express, { Router } from 'express';
import bodyParser from 'body-parser';

let app = express();
let router = Router();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());

router.get('/', (req, res, next) => {
  res.end('Hello World!');
});
app.use('/', router);

app.listen(3000, () => {
  console.log('server listening at port 3000...');
});

<a id="babel-transform">

使用bebel转换

将代码修改为es6语法之后,就可以使用babel进行转换了。
使用命令babel src -d lib
可以看到控制台中显示:

src/app.js -> lib/app.js

之后还是运行一下看看效果,浏览器打开http://localhost:3000,我们和熟悉的Hello World又见面啦。

<a id="gulp">

Gulp

每次修改完代码都要重新用babel转换一次是不是很麻烦?别怕,我们有gulp。

<a id="gulp-install">

安装

npm install -g gulp-cli
npm install --save-dev gulp gulp-babel

<a id="gulpfile">

编写gulpfile

在根目录新建一个gulpfile.babel.js文件。
gulp原生并不支持es6语法,但是我们可以告诉gulp使用babel将gulpfile转换为es5,方法就是将gulpfile命名为gulpfile.babel.js

<a id="gulpfile-default">

一个简单的gulpfile

我们先写一个简单的gulpfile测试一下gulp是否能够正常工作。

import gulp from 'gulp';
import babel from 'gulp-babel';

gulp.task('default', () => {
  return gulp.src('src/**/*.js')
    .pipe(babel())
    .pipe(gulp.dest('lib'));
});

控制台执行gulp,可以看到:

[13:00:35] Requiring external module babel-register
[13:00:36] Using gulpfile /path/to/file/gulpfile.babel.js
[13:00:36] Starting 'default'...
[13:00:36] Finished 'default' after 191 ms

然后lib文件夹下就生成了转换后的文件了。

<a id="gulpfile-watch">

能够监听文件更改的gulpfile

虽然上面的gulpfile能够将使用了,但是还是跟之前直接用babel一样,每次都要gulp一下,下面我们就来写一个能够监听文件的gulpfile。当文件被修改之后,自动将文件转换。
这里使用gulp-watch监听文件更改。
npm install --save-dev gulp-watch

import gulp from 'gulp';
import watch from 'gulp-watch';
import babel from 'gulp-babel';

gulp.task('transform', () => {
  return gulp.src('src/**/*.js')
    .pipe(babel())
    .pipe(gulp.dest('lib'));
});

gulp.task('watch', () => {
  return gulp.src('src/**/*.js')
    .pipe(watch('src/**/*.js', {
      verbose: true
    }))
    .pipe(babel())
    .pipe(gulp.dest('lib'));
});

gulp.task('default', () => {
  gulp.start('transform');
});

控制台执行gulp watch

[14:11:46] Requiring external module babel-register
[14:11:47] Using gulpfile /file/to/path/gulpfile.babel.js
[14:11:47] Starting 'watch'...

然后修改app.js并保存,可以看到控制台中多了一行信息

[14:13:20] app.js was changed

对于gulp其他的用法这里就不细说了,有兴趣的可以去看桑大i5tingGulp实战和原理解析(以weui作为项目实例)

<a id="react-webpack">

React + Webpack

<a id="react-webpack-install">

安装

react
npm install --save react react-dom
webpack
npm install --save-dev webpack webpack-dev-server
为了编译jsx,我们还需要其他一些模块
npm install --save-dev babel-loader babel-preset-react

<a id="webpack-config">

编写webpack.config.js

var path = require('path');
var webpack = require('webpack');

module.exports = {
  devtool: 'eval',
  entry: {
    public: './public/src/index'
  },
  output: {
    path: path.join(__dirname, 'public/dist'),
    filename: 'bundle.js',
    publicPath: 'public/dist'
  },
  plugins: [],
  module: {
    loaders: [
      {
        test: /\.js$/,
        include: [path.join(__dirname, 'public/src')],
        loader: 'babel',
        query: {
          presets: ['react', 'es2015']
        }
      }
    ]
  }
};

<a id="gulp-webpack">

在gulp中使用webpack

修改gulpfile.babel.js,添加buildwebpack-dev-server任务,分别是生成打包文件和启动开发服务器,并将default修改为同时执行transformwebpack-dev-server

import gulp from 'gulp';
import gutil from 'gulp-util';
import watch from 'gulp-watch';
import babel from 'gulp-babel';
import webpack from 'webpack';
import WebpackDevServer from 'webpack-dev-server';

import webpackConfig from './webpack.config.js';

// transform
gulp.task('transform', () => {
  return gulp.src('src/**/*.js')
    .pipe(babel())
    .pipe(gulp.dest('lib'));
});

// watch transform
gulp.task('watch-transform', () => {
  return gulp.src('src/**/*.js')
    .pipe(watch('src/**/*.js', {
      verbose: true
    }))
    .pipe(babel())
    .pipe(gulp.dest('lib'));
});

gulp.task('webpack:build', (callback) => {
  // modify some webpack config options
  var myConfig = Object.create(webpackConfig);
  myConfig.plugins = myConfig.plugins.concat(
    new webpack.DefinePlugin({
      'process.env': {
        // This has effect on the react lib size
        'NODE_ENV': JSON.stringify('production')
      }
    }),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin()
  );

  // run webpack
  webpack(myConfig, (err, stats) => {
    if (err)
      throw new gutil.PluginError('webpack:build', err);
    gutil.log('[webpack:build]', stats.toString({
      colors: true
    }));
    callback();
  });
});

gulp.task('webpack-dev-server', (callback) => {
  // modify some webpack config options
  var myConfig = Object.create(webpackConfig);
  myConfig.devtool = 'eval';
  myConfig.debug = true;

  // Start a webpack-dev-server
  new WebpackDevServer(webpack(myConfig), {
    publicPath: '/' + myConfig.output.publicPath,
    stats: {
      colors: true
    }
  }).listen(3001, 'localhost', (err) => {
    if (err) throw new gutil.PluginError('webpack-dev-server', err);
    gutil.log('[webpack-dev-server]', 'http://localhost:3001/');
  });
});

gulp.task('default', ['watch-transform', 'webpack-dev-server']);

<a id="react">

使用React

在根目录下创建index.html文件

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello Wrold</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="http://127.0.0.1:3001/public/dist/bundle.js"></script>
  </body>
</html>

之后在public/src目录创建index.js文件,简单的写个hello world.

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class App extends Component {
  render() {
    return (
      <h1>Hello Wrold!!</h1>
    );
  }
}

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

控制台执行gulp webpack-dev-server,打开http://localhost:3001
我们和Hello world!第三次见面了~

<a id="summary">

总结

到这里文章就结束了,然而这只是文章的结束,现在只是把大体的结构搭建起来了,剩下要做的还有很多,继续加油把~
PS: 我也不知道这种目录结构是否合理,如有不同意见,欢迎拍砖~

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

推荐阅读更多精彩内容

  • 无意中看到zhangwnag大佬分享的webpack教程感觉受益匪浅,特此分享以备自己日后查看,也希望更多的人看到...
    小小字符阅读 8,134评论 7 35
  • 前言 众所周知目前比较火的工具就是gulp和webpack,但webpack和gulp却有所不同,本人两者的底层研...
    cduyzh阅读 1,354评论 0 13
  • -- 1. Gulp VS webpack 比较 Gulp 是一个任务管理工具,让简单的任务更清晰,让复杂的任务易...
    慢清尘阅读 3,533评论 7 16
  • gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简单,学...
    依依玖玥阅读 3,147评论 7 55
  • 拿了仓库里谁忘记的小刀,算不算假公济私?
    村里的孩子阅读 211评论 0 0