在搭建之前确保已经安装最新版 nodejs
安装 dva
& roadhog
$ npm i dva-cli -g
$ dva -v
0.7.8
$ npm i roadhog -g
$ roadhog -v
0.5.3
创建项目
$ dva new newproject
启动项目
$ cd newproject
$ npm install
$ npm start
打开浏览器访问 http://localhost:8000/ 可以看到欢迎界面
Mac
系统, 如果出现权限问题permission denied, open '/Users/用户名/.babel.json'
请使用sudo chown -R 用户名 ~/.babel.json
解决
.
├── dist # 编译结果
├── mock # 虚拟数据
├── public # 文件夹内所有文件将直接复制到根目录
├── src # Source directory
├── assets # Store images, icons, ...
├── components # UI components
├── index.css # CSS for entry file
├── index.html # HTML for entry file
├── index.js # Enry file
├── models # Dva models
├── router.js # Router configuration
├── routes # Route components
├── services # Used for communicate with server
└── utils # Utils
└── request.js # A util wrapped dva/fetch
├── .editorconfig #
├── .eslintrc # Eslint config
├── .gitignore #
├── .roadhogrc # Roadhog config
└── package.json #
由于 dva
和 roadhog
的版本还没有稳定,用命令生成的新目录不能直接用于开发,需要修改配置文件。
关闭启动时自动开启浏览器新页签功能
{
...
"scripts": {
- "start": "roadhog server",
+ "start": "roadhog server --no-open",
},
...
}
安装依赖并添加至 package.json
# lodash
$ npm i -D lodash
# babel-plugin
$ npm i -S babel-polyfill
$ npm i -D babel-plugin-import babel-plugin-lodash
# eslint-config
$ npm i -D eslint-config-promise
# webpack-plugin
$ npm i -D lodash-webpack-plugin html-webpack-plugin
# shim
$ npm i es5-shim console-polyfill
复制 es5-shim.min.js
es5-sham.min.js
console-polyfill/index.js
文件到 public
文件夹
console-polyfill/index.js
改名为console-polyfill.js
当前版本 roadhog
功能不完善,不过幸好支持读取文件 webpack.config.js
修改配置。
import webpack from 'webpack';
import { isRegExp } from 'lodash';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import LodashModuleReplacementPlugin from 'lodash-webpack-plugin';
// rucksack
// import rucksack from 'rucksack-css';
export default ( webpackConfig, env ) => {
const loaders = webpackConfig.module.loaders;
// rucksack
// const postcss = webpackConfig.postcss;
// webpackConfig.postcss = function () {
// return postcss().unshift( rucksack() );
// };
// 根目录使用相对地址
webpackConfig.output.publicPath = '';
// 不打包 moment.js 的语言包
const noParse = webpackConfig.module.noParse;
if ( Array.isArray( noParse ) ) {
noParse.push( /moment.js/ );
}
else if ( noParse ) {
webpackConfig.module.noParse = [ noParse, /moment.js/ ];
}
else {
webpackConfig.module.noParse = [ /moment.js/ ];
}
// lodash
webpackConfig.babel.plugins.push( 'lodash' );
webpackConfig.plugins.push( new LodashModuleReplacementPlugin() );
// 生成 HTML
webpackConfig.module.loaders = loaders.filter(
loader => isRegExp( loader.test ) && loader.test.toString() !== '/\\.html$/'
);
webpackConfig.plugins.push(
new HtmlWebpackPlugin( {
// favicon: './src/logo/logo.ico',
template: './src/index.html',
filename: 'index.html',
inject: true
// 方便实施人员修改配置 index.html 不压缩
// minify: { //压缩HTML文件
// removeComments: false, //移除HTML中的注释
// collapseWhitespace: false //删除空白符与换行符
// }
} )
);
// 打包配置
if ( env === 'production' ) {
// 字体打包
loaders.unshift( {
test: /\.(woff|woff2|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file',
query: {
name: 'static/[name].[hash:8].[ext]'
}
} );
// 所有输出文件添加 hash
webpackConfig.output.filename = '[name].[chunkhash:6].js';
webpackConfig.output.chunkFilename = '[name].[chunkhash:6].js';
// css common 添加 hash
webpackConfig.plugins.forEach( ( plugin, index, plugins ) => {
if ( plugin instanceof ExtractTextPlugin ) {
plugins[ index ] = new ExtractTextPlugin( '[name].[chunkhash:6].css' );
}
else if ( plugin instanceof webpack.optimize.CommonsChunkPlugin ) {
plugins[ index ] = new webpack.optimize.CommonsChunkPlugin(
'common',
'common.[chunkhash:6].js'
);
}
} );
}
return webpackConfig;
};
详细的
webpack
配置参考roadhog
的 webpack配置注:官方不推荐此方法修改配置,因为不便于以后的完美升级。 由于官方的配置不能完全满足我们的需求,因此
webpack.config.js
配置还是必要的。 当根目录存在webpack.config.js
文件时,运行服务会有警告。
详细文档参考 https://github.com/sorrycc/roadhog
不喜欢
json
格式的配置,可以改名为.roadhogrc.js
使用javascript
语法 支持es6
语法
{
+ "multipage": true,
- "entry": "src/index.js",
+ "entry": ["src/common.js", "src/index.js"],
...
}
编辑器语法检查配置。
统一团队代码风格,调试方便,提高开发效率
{
...
- "extends": "airbnb"
+ "extends": "promise"
...
}
src/index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0">
<title></title>
<!-- /path/to/ 或者 / -->
<base id="basename" href="/" />
<!--[if lt IE 10]>
<script type="text/javascript" src="es5-shim.min.js"></script>
<script type="text/javascript" src="es5-sham.min.js"></script>
<script type="text/javascript" src="console-polyfill.js"></script>
<![endif]-->
</head>
<body>
<div id="root"></div>
</body>
</html>
src/router.js
import React from 'react';
import { Router, Route } from 'dva/router';
import IndexPage from './routes/IndexPage';
function RouterConfig({ history }) {
return (
<Router history={history}>
<Route path="/" component={IndexPage} />
</Router>
);
}
export default RouterConfig;
src/routes/indexPage.jsx
import React from 'react';
import './IndexPage.less';
function IndexPage() {
return (
<div style={{ textAlign: 'center' }}>
<h1>Hello World</h1>
</div>
);
}
IndexPage.propTypes = {};
export default IndexPage;
src/routes/indexPage.less
body {
overflow: hidden;
}
src/index.js
import dva from 'dva';
import './index.css';
// 1. Initialize
const app = dva();
// 2. Plugins
// app.use({});
// 3. Model
// app.model(require('./models/example'));
// 4. Router
app.router(require('./router'));
// 5. Start
app.start('#root');
src/common.js
打包公共库
import 'dva';
import 'react';
import 'react-dom';
import moment from 'moment';
import 'moment/locale/zh-cn';
// 全局设置 locale
moment.locale( 'zh-cn' );
-
删除多与文件,启动开发服务器
$ npm start
打开浏览器访问 http://localhost:8000/ 可以看到 Hello World