react-admin-lte
Version:
简单封装的 AdminLTE react 类库,并包含一个编译配置。
426 lines (396 loc) • 16.1 kB
JavaScript
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const fs = require('fs');
const path = require('path');
const chalk = require('chalk');
const CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin;
const nodeModulesPath = path.resolve(__dirname, 'node_modules');
class Builder {
constructor(options) {
options = options || {};
/**
* 开发目录,这是一个绝对路径。
*/
this.devPath = options.devPath || path.resolve('./dev');
/**
* 需要构建到的目录。
*/
this.buildPath = options.buildPath || path.resolve('./build');
/**
* 目录名称,这是相对于 devPath 的。
* @type {string}
*/
this.resFolder = options.resFolder || 'res';
// this.layoutPath = options.layoutPath || path.join(this.devPath, 'layout.html');
/**
* 环境
* @type {null|string}
*/
this.nodeEnv = options.nodeEnv || 'dev';
/**
* 编译器列表
* @type {{}}
*/
this.jsBuilds = {};
}
newConfig(subPath, filename) {
var srcJs = path.join(this.devPath, subPath, filename + '.js');
// var outPath = path.join(this.buildPath, 'js');
// var htmlFile = path.join(subPath, filename + '.html');
var config = {
context: this.devPath,
entry : {
index: srcJs
},
output : {
path : this.buildPath,
filename: path.join('js', filename + '.js')
},
devtool: "source-map",
module : {
loaders: [
{
test : /\.js$/, // All .js files
loaders: ['babel-loader'], // react-hot is like browser sync and babel loads jsx and es6-7
exclude: [nodeModulesPath]
}]
},
plugins: [
new CommonsChunkPlugin({
children: true,
filename: "commons.js",
name : "commons"
}),
new HtmlWebpackPlugin({
template: 'layout.html',
filename: filename + '.html'
}),
new webpack.DefinePlugin({
"process.env": {
NODE_ENV: JSON.stringify(this.nodeEnv)
}
})
]
};
if (this.nodeEnv == 'product') {
config.plugins.push(
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new webpack.NoErrorsPlugin()
);
} else {
config.plugins.push(
new webpack.HotModuleReplacementPlugin()
);
}
return config;
}
log() {
console.log();
console.log(chalk.bold.bgBlue.white('>>>>>>>>>>>>>>>>>我是前端<<<<<<<<<<<<<<<<<<<'));
console.log(chalk.blue(...arguments));
console.log(chalk.blue(''));
}
copyStatic() {
var resFolder = this.resFolder;
try {
fs.accessSync(path.join(this.buildPath, resFolder), fs.F_OK);
this.log('静态资源文件夹已经存在,跳过拷贝。如果要重新搞,请删除:', path.join(this.buildPath, resFolder));
} catch (e) {
this.log("静态文件资源不存在,拷贝...");
let _this = this;
webpack({
context: this.devPath,
output : {
path: this.buildPath
},
plugins: [
new CopyWebpackPlugin([
{from: resFolder + '/**/*'}
])
]
}, function (err, stats) {
if (err) {
_this.log(err);
} else {
_this.log('静态文件拷贝完成...');
}
});
}
}
walk(currentDirPath, callback) {
let _this = this;
var resFolder = this.resFolder;
fs.readdir(currentDirPath, function (err, files) {
if (err) {
throw new Error(err);
}
files.forEach(function (name) {
var filePath = path.join(currentDirPath, name);
var stat = fs.statSync(filePath);
if (stat.isFile()) {
callback(filePath, stat);
} else if (stat.isDirectory()) {
if (filePath != path.join(_this.devPath, resFolder)) {
_this.walk(filePath, callback);
}
}
});
});
}
batchBuild(noWatch) {
let _this = this;
var buildCB = function (err, stats, filename) {
if (err) {
_this.log(err);
return;
}
var jsonStats = stats.toJson();
if (jsonStats.errors.length > 0) {
console.error('Errors:', jsonStats.errors.join('\n'));
}
if (jsonStats.warnings.length > 0) {
console.warn("Warnings", jsonStats.warnings.join('\n'));
} else {
_this.log("编译成功");
}
//_this.log('编译:', relName, ' 完成...');
};
this.walk(this.devPath, function (filePath, stat) {
var relName = filePath.substr(_this.devPath.length + 1);
var xfile = path.parse(relName);
if (xfile.ext == '.js') {
_this.log("开始编译", relName);
var comp = webpack(
_this.newConfig(xfile.dir, xfile.name), buildCB
);
comp.watch({}, buildCB);
_this.jsBuilds[relName] = comp;
}
});
if (!noWatch) {
let _this = this;
// this.log("监视启动,在 webstorm + windows 上有可能重复编译。");
fs.watch(this.devPath, {recursive: true}, (event, filename)=> {
var xfile = path.parse(filename);
if (xfile.ext == '.js') {
// _this.log(filename, ' 发生改变:', event, '。重新编译....');
if (!_this.jsBuilds.hasOwnProperty(filename)) {
_this.log("没有发现文件的编译器,现在创建", filename);
var comp = webpack(
_this.newConfig(xfile.dir, xfile.name), buildCB
);
comp.watch({}, buildCB);
_this.jsBuilds[filename] = comp;
}
}
});
}
}
genLayout(options) {
options = options || {};
var layoutHtml = `
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>${options.siteName}</title>
<!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<script src="//cdn.bootcss.com/cookie.js/1.2.0/cookie.min.js"></script>
<link rel="stylesheet" href="res/lib/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdn.bootcss.com/font-awesome/4.6.3/css/font-awesome.min.css">
<link rel="stylesheet" href="//cdn.bootcss.com/ionicons/2.0.1/css/ionicons.min.css">
<link rel="stylesheet" href="res/lib/AdminLTE/css/AdminLTE.min.css">
<link rel="stylesheet" href="res/lib/AdminLTE/css/skins/_all-skins.min.css">
<link rel="stylesheet" href="res/lib/AdminLTE/plugins/datatables/dataTables.bootstrap.css">
<!--[if lt IE 9]>
<script src="//cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body class="hold-transition skin-blue sidebar-mini">
<div class="wrapper">
<header class="main-header">
<!-- Logo -->
<a href="#" class="logo">
<!-- mini logo for sidebar mini 50x50 pixels -->
<span class="logo-mini">${options.miniLogo}</span>
<!-- logo for regular state and mobile devices -->
<span class="logo-lg">${options.siteName}</span>
</a>
<nav class="navbar navbar-static-top">
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
<span class="sr-only">Toggle navigation</span>
</a>
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<li class="dropdown notifications-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-bell-o"></i>
<span class="label label-warning">10</span>
</a>
<ul class="dropdown-menu">
<li class="header">您有 10 条新消息</li>
<li>
<!-- inner menu: contains the actual data -->
<ul class="menu">
<li>
<a href="#">
<i class="fa fa-users text-aqua"></i> 5 new members joined today
</a>
</li>
<li>
<a href="#">
<i class="fa fa-warning text-yellow"></i> Very long description here that
may not fit into the
page and may cause design problems
</a>
</li>
<li>
<a href="#">
<i class="fa fa-users text-red"></i> 5 new members joined
</a>
</li>
<li>
<a href="#">
<i class="fa fa-shopping-cart text-green"></i> 25 sales made
</a>
</li>
<li>
<a href="#">
<i class="fa fa-user text-red"></i> You changed your username
</a>
</li>
</ul>
</li>
<li class="footer"><a href="#">看看全部</a></li>
</ul>
</li>
<!-- User Account: style can be found in dropdown.less -->
<li class="dropdown user user-menu">
<a href="#" class="dropdown-toggle avtar" data-toggle="dropdown">
<img src="" class="user-image avatar" alt="用户头像"/>
<span class="hidden-xs nick">123</span>
</a>
<ul class="dropdown-menu">
<!-- User image -->
<li class="user-header">
<img src="" class="img-circle avatar" alt="用户头像">
<p>
<span class="nick">管理员</span>
<small>...</small>
</p>
</li>
<!-- Menu Body -->
<li class="user-body">
<div class="row">
<div class="col-xs-4 text-center">
<a href="#">1</a>
</div>
<div class="col-xs-4 text-center">
<a href="#">2</a>
</div>
<div class="col-xs-4 text-center">
<a href="#">3</a>
</div>
</div>
<!-- /.row -->
</li>
<!-- Menu Footer-->
<li class="user-footer">
<div class="pull-left">
<a href="#" class="btn btn-default btn-flat">更改密码</a>
</div>
<div class="pull-right">
<a href="#" class="btn btn-default btn-flat" id="btnLogout">退出登录</a>
</div>
</li>
</ul>
</li>
<!-- Control Sidebar Toggle Button -->
<li>
<a href="#" data-toggle="control-sidebar"><i class="fa fa-gears"></i></a>
</li>
</ul>
</div>
</nav>
</header>
<!-- Left side column. contains the logo and sidebar -->
<aside class="main-sidebar">
<!-- sidebar: style can be found in sidebar.less -->
<section class="sidebar">
<!-- search form -->
<form action="#" method="get" class="sidebar-form">
<div class="input-group">
<input type="text" name="q" class="form-control" placeholder="查询...">
<span class="input-group-btn">
<button type="submit" name="search" id="search-btn" class="btn btn-flat"><i class="fa fa-search"></i>
</button>
</span>
</div>
</form>
<!-- /.search form -->
<!-- sidebar menu: : style can be found in sidebar.less -->
<ul class="sidebar-menu">
<li class="header"></li>
<li>
<a href="/">
<i class="fa fa-dashboard"></i> <span>仪表盘</span>
</a>
</li>
<li class="treeview">
<a href="#">
<i class="fa fa-cart-arrow-down"></i>
<span>帐号和权限</span>
<i class="fa fa-angle-left pull-right"></i>
</a>
<ul class="treeview-menu">
<li><a href="/account.html"><i class="fa fa-users"></i> 帐号管理</a></li>
<li><a href="/service.html"><i class="fa fa-circle-o"></i> 服务</a></li>
<li><a href="/right.html"><i class="fa fa-circle-o"></i> 应用 URL</a></li>
<li><a href="/address.html"><i class="fa fa-circle-o"></i> 地址管理</a></li>
<li><a href="/district.html"><i class="fa fa-circle-o"></i> 地区管理</a></li>
</ul>
</li>
</ul>
</section>
</aside>
<div class="content-wrapper" id="mainContent"></div>
<footer class="main-footer">
<div class="pull-right hidden-xs">
<b>版本</b> 0.0.1
</div>
<strong>Copyright © 2014-${new Date().getFullYear()} <a href="http://www.itietie.com">${options.siteName}</a>.</strong>
All rights reserved.
</footer>
<aside class="control-sidebar control-sidebar-dark">
<h1>Side bar</h1>
</aside>
<div class="control-sidebar-bg"></div>
</div>
<script src="res/lib/AdminLTE/plugins/jQuery/jQuery-2.2.0.min.js"></script>
<script src="//cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<script src="res/lib/bootstrap/js/bootstrap.min.js"></script>
<script src="res/lib/AdminLTE/js/app.min.js"></script>
</body>
</html>
`;
var devLayout = path.join(this.devPath, 'layout.html');
try {
fs.accessSync(devLayout, fs.F_OK);
this.log('模板文件已经存在,跳过生产。');
} catch (e) {
fs.writeFile(devLayout, layoutHtml, (err)=> {
this.log(`模板文生产成功,#mainContent 这个标签必须留着哦。
菜单什么的的你要自己裁剪啊。AdminLTE 的资源你也要自己拷贝哦,具体请看文档。`);
});
}
}
}
module.exports = Builder;