# generator-peon-static
[![NPM version](https://img.shields.io/npm/v/generator-peon-static.svg?style=flat)](https://www.npmjs.com/package/generator-peon-static)


这是一个基于yeoman的前端[peon](http://code.dianpingoa.com/cortex/peon/tree/master)工程脚手架生成器


## Update

新增vue脚手架
新增react+redux4app 适用于h5项目

2016-09-14
修复redux index.jsx文件多个export报错的问题

## 简介

本generator根据不同业务需求，提供了如下4种脚手架类型可供开发者选择

#### __basic__
最简单的脚手架，未集成任何lib和tool chain,只提供了最基本的html/js/css示例文件
#### __webpack+cortex+es6+less__

集成了`webpack+cortex+babel+es6+less+postcss`，支持`Hot Module Replacement (HMR)` ，自带图片压缩，适合习惯使用传统前端技术栈(`jquery`/`zepto`+`less`)的开发者解决一般复杂度需求，比如各种活动页

#### __webpack+cortex+es6+react+less__

在楼上`webpack+cortex+es6+less`脚手架的基础上增加了对`react`/`css module`的支持，自带图片压缩，对于熟悉react的开发者，建议使用该脚手架来创建项目，但这并不是说所有项目都应该用react，对于逻辑交互比较复杂的需求，使用react有助于降低开发复杂度，一般的偏展示性页面还是建议使用楼上的`webpack+cortex+es6+less`脚手架
	

#### __webpack+cortex+es6+react+redux4app__

在前面react脚手架的基础上增加了对`react+redux`的支持，对于开发复杂应用,为了方便管理数据流,各组件共享数据,简化操作逻辑

#### __webpack+cortex+es6+vue__

基于vue的官方webpack脚手架，集成了cortex。轻量级的数据驱动型Web界面组件。

## 安装
##### 首先安装[yeoman](http://yeoman.io/)(如果已安装请忽略此步)


```sh
npm install -g yo
```

<small>*yeoman是一种脚手架生成工具，方便你快速使用/开发脚手架生成器(generator),类似于npm init或者cortex init，开发者只用输入一些简单的信息，yeoman的generator就能帮你快速生成相应的工程脚手架，开发者无需花过多精力去搭建开发环境*</small>

##### 安装generator-peon-static

```sh
npm install -g generator-peon-static
```

## 初始化项目

```sh
cd /path/of/your/project
yo peon-static
```

根据需要选择不同类型的模板

```sh
? boilerplate (Use arrow keys)
❯ basic 
  webpack+cortex+es6+less 
  webpack+cortex+es6+react+less 
  webpack+cortex+es6+react+redux4app
  webpack+cortex+es6+vue 
```

按提示填写所有project信息后，工具会自动帮我们进行`npm install`,`cortex install`等命令，我们只需要耐心等待所有依赖包安装完毕。

## 构建
#### basic

    暂不支持，请自行配置
#### webpack+cortex+es6+less

```sh
cd /path/of/your/project

//手动构建
webpack

//自动构建
webpack --watch
```

#### webpack+cortex+es6+react+less

```sh
cd /path/of/your/project

//手动构建
webpack

//自动构建
webpack --watch
```
#### webpack+cortex+es6+react+redux4app

```sh
cd /path/of/your/project

//手动构建
webpack

//自动构建
webpack --watch
```

#### webpack+cortex+es6+vue

```sh
cd /path/of/your/project

//手动构建
webpack

//自动构建
webpack --watch
```

## 运行调试
通过`webpack-dev-server`开启本地web server服务器，支持自动构建，支持热部署Hot Module Replacement (HMR)，即每次修改完代码`webpack-dev-server`会自动build并让浏览器自动载入被修改过的模块，开发者无需手动刷新浏览器。


#### basic

    暂不支持，请自行配置

#### webpack+cortex+es6+less
```sh
npm start
```
项目初始化完毕后会自动运行上面的命令开启调试模式

#### webpack+cortex+es6+react+less
```sh
npm start
```
项目初始化完毕后会自动运行上面的命令开启调试模式

#### webpack+cortex+es6+react+redux4app
```sh
npm start
```
项目初始化完毕后会自动运行上面的命令开启调试模式

#### webpack+cortex+es6+vue
```sh
npm run start
```
项目初始化完毕后会自动运行上面的命令开启调试模式

## 发布
不用本地构建，直接发布
1.  git commit and push

2.  CI发布(beta/peon_static)


## 说明和配置

#### basic
待工程初始化完毕后可以看到工程目录如下

	.
	├── LICENSE
	├── README.md
	├── f2eci.json
	├── gulpfile.js
	├── node_modules
	│   ├── ...
	├── html
	│   ├── static
	│   │   ├── test.css
	│   │   └── test.js
	│   └── test.html
	├── index.js
	└── package.json

	
*   所有要发布的html文件都在./html目录下，./html/test.html是最简单的示例页面
	
*   webpack执行的时候会执行gulp命令，将./html目录下的所有文件复制到./dist目录下，CI会将./dist目录下的所有文件发布到CDN上

*   ./f2eci.json为peon的配置文件，具体参考[这里](http://code.dianpingoa.com/cortex/peon/tree/master)

#### webpack+cortex+es6+less
待工程初始化完毕后可以看到工程目录如下

```
.
├── LICENSE
├── README.md
├── cortex.json
├── f2eci.json
├── gulpfile.js
├── html
│   ├── static
│   │   └── i
│   │       └── icon-right.png
│   └── test.html   //示例html页面
├── index.js
├── package.json
├── server.js   //webpack-dev-server启动配置文件
├── src
│   ├── lib
│   │   └── hello.es6
│   └── pages
│       └── test
│           ├── assets  //静态资源
│           │   ├── i   //图片
│           │   │   ├── icon-wrong.png
│           │   │   └── upload.png
│           │   └── styles  //样式
│           │       └── global.less
│           └── boot-loader.es6 //test.html的入口文件
├── webpack
│   ├── webpack.base.config.js
│   ├── webpack.beta.config.js
│   ├── webpack.dev.config.js
│   └── webpack.product.config.js
└── webpack.config.js
```
*   所有js源码均为es6版本(*.es6)
*   ./webpack.config.js会根据不同的环境引入相应的webpack配置文件，大部分基础webpack配置都在./webpack/webpack.base.config.js里。
比如新增入口js只需在./webpack/webpack.base.config.js中修改添加entry即可

*   所有入口html文件应该放在./html目录下，比如./html/test.html

*   webpack会将所有生成的静态资源放到./dist/static目录下，要自定义目录，请修改./f2eci.json文件中的`dist`字段和`static-src`字段

*   如同`basic`脚手架一样，CI在构建时会通过gulp将./html下的所有文件复制到./dist中，并将./dist中的文件部署到远程CDN上

*   所有代码都应放到./src目录下，不同页面对应的资源应放在./src/pages/[page-name]目录下
*   所有公共代码都应放到./src/lib目录下


#### webpack+cortex+es6+react+less
待工程初始化完毕后可以看到工程目录如下

```
.
├── LICENSE
├── README.md
├── cortex.json
├── f2eci.json
├── gulpfile.js
├── html
│   ├── static
│   │   └── i
│   │       └── icon-right.png
│   └── test.html   //示例html页面
├── index.js
├── npm-debug.log
├── package.json
├── server.js
├── src
│   ├── lib
│   │   └── hello.es6
│   └── pages
│       └── test
│           ├── assets
│           │   ├── i
│           │   │   ├── icon-wrong.png
│           │   │   └── upload.png
│           │   └── styles
│           │       ├── global.less
│           │       └── index.less.module
│           ├── boot-loader.jsx //test.html的入口文件
│           └── index.jsx   //react组件test的入口文件
├── webpack
│   ├── webpack.base.config.js
│   ├── webpack.beta.config.js
│   ├── webpack.dev.config.js
│   └── webpack.product.config.js
└── webpack.config.js

```
同`webpack+cortex+es6+less`脚手架一样
*   所有js源码均为es6版本(*.es6)
\*   ./webpack.config.js会根据不同的环境引入相应的webpack配置文件，大部分基础webpack配置都在./webpack/webpack.base.config.js里。
比如新增入口js只需在./webpack/webpack.base.config.js中修改添加entry即可

*   所有入口html文件应该放在./html目录下，比如./html/test.html

*   webpack会将所有生成的静态资源放到./dist/static目录下，要自定义目录，请修改./f2eci.json文件中的`dist`字段和`static-src`字段

*   如同`basic`脚手架一样，CI在构建时会通过gulp将./html下的所有文件复制到./dist中，并将./dist中的文件部署到远程CDN上

*   所有代码都应放到./src目录下，不同页面对应的资源应放在./src/pages/[page-name]目录下
*   所有公共代码都应放到./src/lib目录下
*   作用域为全局的样式文件以.less或者.css结尾
*   模块内作用域的样式文件以.less.module或者.css.module结尾
*   react的jsx(*.jsx)代码规范请参考[airbnb](https://github.com/airbnb/javascript/tree/master/react)


#### webpack+cortex+es6+react+redux4app
待工程初始化完毕后可以看到工程目录如下

```
.
├── LICENSE
├── README.md
├── cortex.json
├── f2eci.json
├── gulpfile.js
├── html
│   ├── static
│   │   └── i
│   │       └── icon-right.png
│   └── index.html   //示例html页面
├── index.js
├── npm-debug.log
├── package.json
├── server.js
├── src
│   ├── common
│   │   └── css
│   │   │   └─── 各种初始化页面样式less
│   │   └───js    
│   │       └─── 工具函数
│   └── pages
│       └── test
│           ├── assets
│           │   ├── i
│           │   │   ├── icon-wrong.png
│           │   │   └── upload.png
│           │   └── styles
│           │       ├── global.less
│           │       ├── index.less//主页面入口less
│           │       └── index.less.module
│           ├── container //容器组件,可做单独注入的组件
│           ├── boot-loader.jsx //test.html的入口文件
│           └── index.jsx   //react组件test的入口文件
├── webpack
│   ├── webpack.base.config.js
│   ├── webpack.beta.config.js
│   ├── webpack.dev.config.js
│   └── webpack.product.config.js
└── webpack.config.js

```
同`webpack+cortex+es6+less`脚手架一样
*   所有js源码均为es6版本(*.es6)
\*   ./webpack.config.js会根据不同的环境引入相应的webpack配置文件，大部分基础webpack配置都在./webpack/webpack.base.config.js里。
比如新增入口js只需在./webpack/webpack.base.config.js中修改添加entry即可

*   所有入口html文件应该放在./html目录下，比如./html/test.html

*   webpack会将所有生成的静态资源放到./dist/static目录下，要自定义目录，请修改./f2eci.json文件中的`dist`字段和`static-src`字段

*   如同`basic`脚手架一样，CI在构建时会通过gulp将./html下的所有文件复制到./dist中，并将./dist中的文件部署到远程CDN上

*   所有代码都应放到./src目录下，不同页面对应的资源应放在./src/pages/[page-name]目录下
*   所有公共代码都应放到./src/lib目录下
*   作用域为全局的样式文件以.less或者.css结尾
*   模块内作用域的样式文件以.less.module或者.css.module结尾
*   react的jsx(*.jsx)代码规范请参考[airbnb](https://github.com/airbnb/javascript/tree/master/react)

#### webpack+cortex+es6+vue
待工程初始化完毕后可以看到工程目录如下

```
.
├── LICENSE
├── README.md
├── cortex.json
├── f2eci.json
├── gulpfile.js
├── html
│   └── index.html   //示例html页面
├── index.html
├── package.json
├── src
│   ├── main.js   //项目入口文件
│   └── App.vue   //vue应用入口文件
└── webpack.config.js

```
*   所有js源码均为es6版本

*   所有入口html文件应该放在./html目录下，比如./html/index.html

*   如同`basic`脚手架一样，CI在构建时会通过gulp将./html下的所有文件复制到./dist中，并将./dist中的文件部署到远程CDN上

*   所有代码都应放到./src目录下

*   vue入门文档请参考 [cn.vuejs.org](https://cn.vuejs.org/)

#### 关于HTML文件
###### *静态化html*
将html文件放到./html中，CI会将./html目录下的文件复制到./dist中，并直接部署到cdn上，用户直接通过访问cdn上的xxx.html来展示页面
*   html发布后的beta环境地址为http://h5.51ping.com/app/[project-name]/[page-name].html
*   html发布后的线上地址为http://h5.dianping.com/app/[project-name]/[page-name].html
*   静态资源文件地址为http://www.dpfile.com/app/[project-name]/path/to/file.min.md5.js

html示例文件如下

```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

    <title>大众点评</title>
    <meta name="description" content=""/>
    <meta name="format-detection" content="telephone=no">
    <meta name="format-detection" content="email=no"/>
    <link rel="stylesheet" type="text/css" href="./static/[webpack-entry-name].css" />  //webpack生成的样式文件
</head>
<body>
<div id="app">

</div>
<script type="text/javascript">
    var _hip = [    //初始化打点配置
        ['_autoPV', false]
    ];



    var store={
        info:"Toasted by @cortex/wepp-module-toast"
    };
</script>
<script type="text/javascript" src="./static/common.js"></script>   //webpack生成的lib文件
<script type="text/javascript" src="./static/[webpack-entry-name].js"></script> //webpack生成的entry文件

</body>
</html>

```

###### *动态生成html*
一般我们使用java的ftl来实现动态页面

ftl示例文件如下

```ftl
<#assign cortex=JspTaglibs["http://www.dianping.com/neocortex"]>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

    <title>大众点评</title>
    <meta name="description" content=""/>
    <meta name="format-detection" content="telephone=no">
    <meta name="format-detection" content="email=no"/>
    <link rel="stylesheet" type="text/css" href="<@cortex.staticResource decorate="false" resources="/app/[project-name]]/static/[webpack-entry-name].css" />" />

</head>
<body>
<div id="app"></div>
<script type="text/javascript">
    var _hip = [
        ['_autoPV', false]
    ];
    var store={
        info:'Hello World'
    };
</script>
<script type="text/javascript" src="<@cortex.staticResource decorate="false" resources="/app/[project-name]]/static/common.js" />"></script>
<script type="text/javascript" src="<@cortex.staticResource decorate="false" resources="/app/[project-name]]/static/[webpack-entry-name].js" />"></script>

</body>
</html>
```

具体ftl标签请看参考[这里](http://code.dianpingoa.com/f2e/neocortex-4j/tree/master)

## 如何用webpack组织代码

#### 入口
入口js必须自执行,例如

```javascript
class BootLoader  {
    constructor (props) {
        if (!_ins) {
            _ins=this;
        }
        return _ins;
    }

    static getInstance() {
        if (!_ins) {
            _ins=new BootLoader();
        }
        return _ins;
    }

    init() {
        ReactDom.render(<Test />, document.getElementById('app'));
    }
}

BootLoader.getInstance().init();
````


#### 同步加载
###### *加载lib文件夹下的文件*

当pages下目录结构非常复杂的时候，要引用lib下的js会导致相对路径非常长，我们可以使用自定义短名的方式去引用lib下的js


```javascript
import Example from '@lib/a/b/c/example.js';
```
###### *加载npm包*

先安装要加载的包

```sh
npm install react --save
```

再在代码中引用

```javascript
import React from 'react';

```

###### *加载cortex包*

比如我要加载cortex下的Toast包

先用cortex安装Toast包

```sh
cortex install wepp-module-toast
```

再在代码中引用

```javascript
import Toast from "@cortex/wepp-module-toast";

...

Toast("Hello World");

...
```


###### *加载样式文件*
支持css,less文件，若要支持其他样式文件请自行配置webpack中的loader

加载全局样式文件(必须以.less结尾)

```javascript
import './assets/styles/base.less.global';

```


加载模块级作用域的样式文件CSSModules（配合react或其他js框架使用）


./assets/styles/index.less.module

```style

.red {
	color:#ff0000;
	font-size:20px;
}

```

```javascript
import styles from './assets/styles/index.less.module';//*.less.module样式文件默认以css modules模式载入
class App extends React.Component {
    constructor () {
        super();
    }

    render() {
        return (//react css modules示例
            <div className={styles.red}>
            	I'm red.
            </div>
       );
    }
}

```

`.red`样式的作用域只局限于该react component,这样就可以随便写样式class name而不必担心命名空间污染的问题

###### *加载图片*
webpack会对所有图片进行压缩处理

*   样式中引入图片

    在样式文件中正常引入图片即可，所有图片将以base64的方式打入js中

*   DOM中引入图片

    ```javascript
    import icon from './assets/i/icon-wrong.png';

    ...

    render() {
        return (<img class="img" src={icon}/>)
    }

    ...

    ```

###### *异步加载*

webpack支持异步加载js文件

```javascript
require.ensure([],(require)=>{//异步加载JS示例
        var Hello = require('../lib/hello.es6').default;
        Hello.sayHelloWorld();
});
```

## cortex in webpack
通过引入`cortex-recombiner-webpack-plugin`使得webpack支持cortex包

webpack.base.config.js

```js
var CortexRecombinerPlugin=require('cortex-recombiner-webpack-plugin');

...

module.exports={
    ...
    plugins: [
        new CortexRecombinerPlugin({
            base:path.resolve(__dirname,relativeToRootPath),//项目根目录的绝对路径
        })
    ]
    ...
}


````

## 打点
*	必须现在html中进行打点初始化配置

```javascript
var _hip = [//如果需要打点,此设置必须
    ['_autoPV', false]//手动关闭自动PV打点,打点逻辑自行添加到js相关代码中
];
```
*	入口中显示引入hippo库

```javascript/es6
import Hippo from '@cortex/hippo';//对于cortex包的引入,需在包名前加上@cortex/的前缀以示区分
```


*	显示打点

```javascript
_hip.push(['_setPageId', 12345]);
_hip.push(['pv']);
```

更多打点规范请参考[官方打点文档](http://code.dianpingoa.com/f2ei-private/hippo3/tree/master)

## 注意
*   在使用本生成器之前，记得切换为公司内部的npm源，cortex源

```
npm config set registry http://r.npmjs.dp
cortex config set registry http://registry.cortex.dp
```

*   为了更容易发现问题，请将本地node版本与线上CI同步（当前CI node版本为v4.3.1）




*   引入cortex包的时候必须以@cortex/xxx的包名形式引入


```javascript
import Toast from "@cortex/wepp-module-toast";
```

*   html中必须先载入库文件common.js再载入入口文件index.js
如果要使用打点功能，必须在html/ftl中显示初始化

```javascript
var _hip = [//如果需要打点,此设置必须
    ['_autoPV', false]//手动关闭自动PV打点,打点逻辑自行添加到js相关代码中
];
```

## 去除图片压缩模块

因为webpack的图片压缩模块```image-webpack-loader```安装时需要本地编译，所以会非常缓慢，导致CI上线发布时会造成构建进程假死的问题。因此新版本的generator-peon-static去掉了图片压缩模块。

*   对于新建项目，直接升级generator-peon-static到最新版本即可

    ```
    npm update -g generator-peon-static
    ```

*   对于已使用老版本生成的项目，需要手动去除图片压缩模块，步骤如下

    去掉```your_project/package.json```里的```devDependencies```下的```image-webpack-loader```模块

    ```
            "image-webpack-loader": "^1.8.0",//删掉这行

    ```

    找到```your_project/webpack/webpack.base.config.js```文件,将

    ```
            test: /\.(jpe?g|png|gif|svg)$/i,
            loaders: env == "dev" ? ["url?limit=25000"] : [
                'url?limit=25000',
                'image-webpack?progressive&optimizationLevel=3&interlaced=false'
             ]
    ```

    改为

    ```
        test: /\.(jpe?g|png|gif|svg)$/i,
        loaders: ["url?limit=25000"]
    ```

    重新提交代码构建即可