UNPKG

react-admin-lte

Version:

简单封装的 AdminLTE react 类库,并包含一个编译配置。

426 lines (396 loc) 16.1 kB
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 = ` <!DOCTYPE html> <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 &copy; 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;