Use Webpack for application processing

* Use Webpack to bundle all assets (images, fonts)
* Use Webpack to process stylesheets
* Remove Gulp
* Define npm scripts in package.json
* Cleanup dependencies in package.json

Implements: blueprint webpack-tooling
Change-Id: I00142c8c33b5b7e043024c51d68321908c9e9cb8
This commit is contained in:
Jiri Tomasek
2016-07-12 10:08:24 +02:00
parent a59093e876
commit 68b04b8c5b
17 changed files with 169 additions and 198 deletions

3
.babelrc Normal file
View File

@@ -0,0 +1,3 @@
{
"presets": ["es2015", "stage-0", "react"]
}

9
.gitignore vendored
View File

@@ -1,10 +1,7 @@
node_modules
dist/tripleo_ui_config.js
dist/js
dist/css
dist/fonts
dist/img
dist/.module-cache
dist
!dist/index.html
!dist/tripleo_ui_config.js.sample
tests_results.xml
.DS_Store
.idea

View File

@@ -111,13 +111,13 @@ Temporary: set ```auth_strategy=noauth```
and restart ironic ```systemctl restart openstack-ironic-api```
## Running the App
## Running the App in Development environment
1. ```git clone https://github.com/openstack/tripleo-ui.git```
2. ```cd tripleo-ui```
3. Install Gulp globally ```sudo npm install -g gulp```
4. Install dependencies ```npm install```
5. Serve the App ```gulp```
5. Start the development server with ```npm start```
5. Optionally start Karma to run tests after every change ```npm run test:watch```
6. Navigate to ```http://<machine_hostname>:3000/```
#### NPM install troubleshooting
@@ -125,10 +125,6 @@ and restart ironic ```systemctl restart openstack-ironic-api```
In case of errors during ```npm install```, remove node_modules dir and clean npm cache
```npm cache clean```. Then run ```npm install``` again.
Temporary:
reqwest has a temporary issue in latest version. Downgrade to 2.0.2 to work around ```npm install reqwest@2.0.2```.
(https://github.com/ded/reqwest/issues/204#issuecomment-145295384)
## Contributing
@@ -138,7 +134,7 @@ Use OpenStack Gerrit for patches and reviews (http://docs.openstack.org/infra/ma
2. Install git-review ```sudo dnf install git-review```
3. Setup Gerrit by running ```git review -s```
4. Develop on feature-branch locally
5. run ```git review``` to push patch for review.
5. Run ```git review``` to push patch for review.
6. Review and merge patches on OpenStack Gerrit: https://review.openstack.org/#/q/project:openstack/tripleo-ui
@@ -148,7 +144,6 @@ Use OpenStack Gerrit for patches and reviews (http://docs.openstack.org/infra/ma
- ```npm test``` (alternatively run ```karma start --single-run```)
- ```npm run lint``` to run ESLint
- ```npm test && npm run lint``` to run Tests and ESLint
(Info on Linting setup here: https://medium.com/@dan_abramov/lint-like-it-s-2015-6987d44c5b48,
.eslintrc rules tweaks here: http://blog.javascripting.com/2015/09/07/fine-tuning-airbnbs-eslint-config/)
@@ -166,7 +161,8 @@ src/js/components/environment_configuration
#### Tests during development:
By running ```gulp serve``` (or ```gulp``` as a shortcut), karma server is also started, and tests are run every time any .js file is saved. In case you want to explicitly run the tests, run ```gulp test-run```.
Start Karma to run tests after every change ```npm run test:watch```
#### Debugging tests
@@ -184,7 +180,7 @@ By running ```gulp serve``` (or ```gulp``` as a shortcut), karma server is also
## Documentation
Use JSDoc docstrings in code to provide source for autogenerated documentation (http://usejsdoc.org/).
Use JSDoc docstrings in code to provide source for autogenerated documentation (http://usejsdoc.org/).
## Basic OpenStack API Usage

3
dist/index.html vendored
View File

@@ -5,11 +5,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>TripleO</title>
<link rel="stylesheet" href="/css/base.css" />
</head>
<body>
<div id="react-app-index"></div>
<script src="/tripleo_ui_config.js"></script>
<script src="/js/tripleo_ui.js"></script>
<script src="/tripleo_ui.js"></script>
</body>
</html>

View File

@@ -1,75 +0,0 @@
var fs = require('fs');
var gulp = require('gulp');
var browserSync = require('browser-sync');
var historyApiFallback = require('connect-history-api-fallback');
var less = require('gulp-less');
// var rename = require('gulp-rename');
var shell = require('gulp-shell');
// var uglify = require('gulp-uglify');
var webpack = require('webpack-stream');
var webpackConfig = require('./webpack.config.js');
var tempStorageWorkerConfig = require('./tempstorageworker.webpack.config.js');
gulp.task('webpack-app', ['webpack-tempstorage-worker'], function() {
return gulp.src('./src/js/index.js')
.pipe(webpack(webpackConfig))
.pipe(gulp.dest('dist/js'))
.pipe(browserSync.stream());
});
gulp.task('serve', ['webpack-app', 'less', 'fonts', 'images'], function(){
browserSync.init({
open: false,
server: {
baseDir: './dist',
middleware: [ historyApiFallback() ]
}
});
gulp.watch('src/less/**/*.less', ['less']);
// Re-build app and run tests on app change.
gulp.watch('src/js/**/*.js', ['webpack-app', 'test-run']);
// Run tests on test change.
gulp.watch('src/__tests__/**/*.js', ['test-run']);
gulp.watch('src/*.html').on('change', browserSync.reload);
});
gulp.task('less', function () {
return gulp.src('./src/less/base.less')
.pipe(less())
.pipe(gulp.dest('./dist/css'))
.pipe(browserSync.stream());
});
gulp.task('fonts', function() {
var bootstrapFonts = 'node_modules/bootstrap/fonts/*';
var patternflyFonts = 'node_modules/patternfly/dist/fonts/*';
var fontAwesomeFonts = 'node_modules/patternfly/components/font-awesome/fonts/*';
return gulp.src([bootstrapFonts, patternflyFonts, fontAwesomeFonts])
.pipe(gulp.dest('./dist/fonts'));
});
gulp.task('images', function() {
var imagesPath = 'src/img/*';
var patternFlyImagesPath = 'node_modules/patternfly/dist/img/*';
return gulp.src([patternFlyImagesPath, imagesPath])
.pipe(gulp.dest('./dist/img'));
});
gulp.task('webpack-tempstorage-worker', function() {
return gulp.src('./src/js/workers/TempStorageWorker.js')
.pipe(webpack(tempStorageWorkerConfig))
.pipe(gulp.dest('./dist/js'));
});
// Start test server, run tests once, then quit.
gulp.task('test', shell.task('karma start --single-run'));
// Start test server, run tests, keep server running..
gulp.task('test-start', shell.task('karma start'));
// Do a single test run (expects Karma server to be running).
gulp.task('test-run', shell.task('karma run'));
gulp.task('default', [ 'serve', 'test-start' ], function() {});

View File

@@ -10,7 +10,7 @@ module.exports = function(config) {
// The entry point for our test suite
basePath: 'src',
autoWatch: false,
autoWatch: true,
files: ['webpack.tests.js'],
preprocessors: {
// Run this through webpack, and enable inline sourcemaps

View File

@@ -5,14 +5,11 @@
"main": "index.js",
"dependencies": {
"babel-core": "^6.0.0",
"babel-loader": "^6.0.0",
"babel-polyfill": "^6.0.0",
"babel-preset-es2015": "^6.0.0",
"babel-preset-react": "^6.0.0",
"babel-preset-stage-0": "^6.5.0",
"bootstrap": "~3.3.5",
"classnames": "~2.2.5",
"connect-history-api-fallback": "~1.2.0",
"formatjs": "^0.1.1",
"formsy-react": "~0.18.0",
"immutable": "~3.8.1",
@@ -29,6 +26,7 @@
"react-redux": "~4.4.5",
"react-router": "~2.4.0",
"redux": "~3.5.2",
"redux-logger": "~2.6.1",
"redux-thunk": "~2.1.0",
"reqwest": "~2.0.1",
"reselect": "^2.0.3",
@@ -38,15 +36,11 @@
},
"devDependencies": {
"babel-eslint": "6.0.4",
"browser-sync": "~2.12.8",
"babel-loader": "^6.0.0",
"css-loader": "~0.23.1",
"eslint": "2.10.2",
"eslint-plugin-react": "5.1.1",
"gulp": "~3.9.0",
"gulp-less": "~3.1.0",
"gulp-rename": "~1.2.2",
"gulp-shell": "~0.5.2",
"gulp-uglify": "~1.5.3",
"webpack-stream": "^3.1.0",
"file-loader": "~0.9.0",
"jasmine": "~2.4.1",
"jasmine-immutable-matchers": "^1.0.1",
"karma": "~0.13.9",
@@ -56,15 +50,22 @@
"karma-phantomjs-launcher": "~1.0.0",
"karma-sourcemap-loader": "~0.3.5",
"karma-webpack": "~1.7.0",
"node-libs-browser": "~1.0.0",
"less": "~2.7.1",
"less-loader": "~2.2.3",
"phantomjs-prebuilt": "~2.1.7",
"react-addons-test-utils": "~15.0.2",
"redux-logger": "~2.6.1",
"shared-worker-loader": "~0.1.0",
"style-loader": "~0.13.1",
"url-loader": "~0.5.7",
"webpack": "~1.13.0",
"phantomjs-prebuilt": "~2.1.7"
"webpack-dev-server": "~1.14.1"
},
"scripts": {
"test": "karma start --single-run",
"lint": "eslint src"
"test:watch": "karma start",
"lint": "eslint src",
"start": "webpack-dev-server --progress",
"build": "webpack"
},
"repository": {
"type": "git",

View File

@@ -1,5 +1,5 @@
import TempStorage from '../../js/services/TempStorage.js';
const WORKER_URL = '/js/tripleo_ui_tempstorage_worker.js';
import TempStorageWorker from '../../js/workers/TempStorageWorker';
describe('TempStorage', () => {
describe('.getItem', () => {
@@ -22,7 +22,7 @@ describe('TempStorage', () => {
let worker;
if(window && window.SharedWorker) {
worker = new window.SharedWorker(WORKER_URL);
worker = new TempStorageWorker();
worker.port.start();
}

View File

@@ -9,6 +9,9 @@ import LoginInput from './ui/forms/LoginInput';
import LoginActions from '../actions/LoginActions';
import NotificationsToaster from './notifications/NotificationsToaster';
import LogoSvg from '../../img/logo.svg';
import TripleoOwlSvg from '../../img/tripleo-owl.svg';
class Login extends React.Component {
constructor() {
super();
@@ -52,13 +55,13 @@ class Login extends React.Component {
return (
<div>
<span id="badge">
<img src="/img/logo.svg" alt="TripleO"></img>
<img src={LogoSvg} alt="TripleO"></img>
</span>
<div className="container">
<div className="row">
<div className="col-sm-12">
<div id="brand">
<img src="/img/tripleo-owl.svg" alt="TripleO"></img>
<img src={TripleoOwlSvg} alt="TripleO"></img>
</div>
</div>
<div className="col-sm-7 col-md-6 col-lg-5 login">

View File

@@ -4,6 +4,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import NavTab from './ui/NavTab';
import TripleoOwlSvg from '../../img/tripleo-owl.svg';
export default class NavBar extends React.Component {
logout(e) {
@@ -24,7 +25,7 @@ export default class NavBar extends React.Component {
<span className="icon-bar"></span>
</button>
<Link className="navbar-brand" to="/">
<img src="/img/tripleo-owl.svg" alt="TripleO"></img>
<img src={TripleoOwlSvg} alt="TripleO"></img>
</Link>
</div>
<div className="navbar-collapse collapse" id="tripleo-navbar-collapse">

View File

@@ -33,6 +33,8 @@ import RegisteredNodesTabPane from './components/nodes/RegisteredNodesTabPane';
import TempStorage from './services/TempStorage.js';
import store from './store';
import '../less/base.less';
TempStorage.initialized.then(() => {
/**
* @function checkAuth

View File

@@ -1,6 +1,6 @@
import when from 'when';
const WORKER_URL = '/js/tripleo_ui_tempstorage_worker.js';
import TempStorageWorker from '../workers/TempStorageWorker';
class TempStorage {
@@ -15,7 +15,7 @@ class TempStorage {
_createWorkerInstance() {
if(window && window.SharedWorker) {
this.worker = new window.SharedWorker(WORKER_URL);
this.worker = new TempStorageWorker();
this.worker.port.start();
}
}

View File

@@ -1,8 +1,8 @@
/*
Combination of default Patternfly import files:
@import "../../node_modules/patternfly/less/patternfly.less";
@import "../../node_modules/patternfly/less/patternfly-additions.less";
@import "~patternfly/less/patternfly.less";
@import "~patternfly/less/patternfly-additions.less";
is broken at the moment because patternfly-additions.less file imports
bootstrap dependencies that in a wrong way override sylesheets defined
@@ -19,71 +19,70 @@
/* PatternFly additions to Bootstrap - patternfly-additions.less part 1 */
// Bootstrap variables and mixins
@import "../../node_modules/patternfly/less/lib/bootstrap/variables.less";
@import "../../node_modules/patternfly/less/lib/bootstrap/mixins.less";
@import "~patternfly/less/lib/bootstrap/variables.less";
@import "~patternfly/less/lib/bootstrap/mixins.less";
// Font Awesome variables
@import "../../node_modules/patternfly/less/lib/font-awesome/variables.less";
@import "~patternfly/less/lib/font-awesome/variables.less";
// Bootstrap-Combobox
@import "../../node_modules/patternfly/less/lib/bootstrap-combobox/combobox.less";
@import "~patternfly/less/lib/bootstrap-combobox/combobox.less";
// Bootstrap-Datepicker
@import "../../node_modules/patternfly/less/lib/bootstrap-datepicker/datepicker3.less";
@import "~patternfly/less/lib/bootstrap-datepicker/datepicker3.less";
// Bootstrap-Select
@import "../../node_modules/patternfly/less/lib/bootstrap-select/bootstrap-select.less";
@import "~patternfly/less/lib/bootstrap-select/bootstrap-select.less";
// Bootstrap Switch
@import "../../node_modules/patternfly/less/lib/bootstrap-switch/bootstrap-switch.less";
@import "~patternfly/less/lib/bootstrap-switch/bootstrap-switch.less";
// Bootstrap Touchspin
@import (less) "../../node_modules/patternfly/less/lib/bootstrap-touchspin/jquery.bootstrap-touchspin.css";
@import (less) "~patternfly/less/lib/bootstrap-touchspin/jquery.bootstrap-touchspin.css";
// C3 charts
@import (less) "../../node_modules/patternfly/less/lib/c3/c3.css";
@import (less) "~patternfly/less/lib/c3/c3.css";
// Bootstrap-DateTimePicker
@import "../../node_modules/patternfly/less/lib/eonasdan-bootstrap-datetimepicker/bootstrap-datetimepicker-build.less";
@import "~patternfly/less/lib/eonasdan-bootstrap-datetimepicker/bootstrap-datetimepicker-build.less";
/* Patternfly */
@import "../../node_modules/patternfly/less/patternfly.less";
@import "~patternfly/less/patternfly.less";
/* Patternfly additions - patternfly-additions.less part 2 */
@import "../../node_modules/patternfly/less/variables.less";
@import "../../node_modules/patternfly/less/mixins.less";
@import "../../node_modules/patternfly/less/blank-slate.less";
@import "../../node_modules/patternfly/less/bootstrap-combobox.less";
@import "../../node_modules/patternfly/less/bootstrap-datepicker.less";
@import "../../node_modules/patternfly/less/bootstrap-select.less";
@import "../../node_modules/patternfly/less/bootstrap-switch.less";
@import "../../node_modules/patternfly/less/bootstrap-touchspin.less";
@import "../../node_modules/patternfly/less/bootstrap-treeview.less";
@import "../../node_modules/patternfly/less/cards.less";
@import "../../node_modules/patternfly/less/charts.less";
@import "../../node_modules/patternfly/less/close.less";
@import "../../node_modules/patternfly/less/datatables.less";
@import "../../node_modules/patternfly/less/footer.less";
@import "../../node_modules/patternfly/less/icons.less";
@import "../../node_modules/patternfly/less/infotip.less";
@import "../../node_modules/patternfly/less/layouts.less";
@import "../../node_modules/patternfly/less/list-view.less";
@import "../../node_modules/patternfly/less/login.less";
@import "../../node_modules/patternfly/less/navbar.less";
@import "../../node_modules/patternfly/less/navbar-alt.less";
@import "../../node_modules/patternfly/less/navbar-vertical.less";
@import "../../node_modules/patternfly/less/nav-vertical-alt.less";
@import "../../node_modules/patternfly/less/search.less";
@import "../../node_modules/patternfly/less/sidebar.less";
@import "../../node_modules/patternfly/less/spinner.less";
@import "../../node_modules/patternfly/less/syntax-highlighting.less";
@import "../../node_modules/patternfly/less/time-picker.less";
@import "../../node_modules/patternfly/less/toast.less";
@import "../../node_modules/patternfly/less/toolbar.less";
@import "../../node_modules/patternfly/less/vertical-nav.less";
@import "~patternfly/less/variables.less";
@import "~patternfly/less/mixins.less";
@import "~patternfly/less/blank-slate.less";
@import "~patternfly/less/bootstrap-combobox.less";
@import "~patternfly/less/bootstrap-datepicker.less";
@import "~patternfly/less/bootstrap-select.less";
@import "~patternfly/less/bootstrap-switch.less";
@import "~patternfly/less/bootstrap-touchspin.less";
@import "~patternfly/less/bootstrap-treeview.less";
@import "~patternfly/less/cards.less";
@import "~patternfly/less/charts.less";
@import "~patternfly/less/close.less";
@import "~patternfly/less/datatables.less";
@import "~patternfly/less/footer.less";
@import "~patternfly/less/icons.less";
@import "~patternfly/less/infotip.less";
@import "~patternfly/less/layouts.less";
@import "~patternfly/less/list-view.less";
@import "~patternfly/less/login.less";
@import "~patternfly/less/navbar.less";
@import "~patternfly/less/navbar-alt.less";
@import "~patternfly/less/navbar-vertical.less";
@import "~patternfly/less/nav-vertical-alt.less";
@import "~patternfly/less/search.less";
@import "~patternfly/less/sidebar.less";
@import "~patternfly/less/spinner.less";
@import "~patternfly/less/syntax-highlighting.less";
@import "~patternfly/less/time-picker.less";
@import "~patternfly/less/toast.less";
@import "~patternfly/less/toolbar.less";
@import "~patternfly/less/vertical-nav.less";
/* TripleO UI styles */
@import "utils/variables";
@import "utils/patternflyOverrides";
@import "ui/Forms";
@import "ui/Grid";

View File

@@ -5,7 +5,7 @@
.login-pf {
background-color: @login-bg-color;
@media (min-width: @screen-sm-min) {
background-image: url("@{img-path}/@{img-bg-login-2}");
background-image: url("../../img/bg-login-2.png");
background-position: 100% 100%;
background-repeat: no-repeat;
background-size: 30%;
@@ -19,7 +19,7 @@
body {
background: transparent;
@media (min-width: @screen-sm-min) {
background-image: url("@{img-path}/@{img-bg-login}");
background-image: url("../../img/bg-login.png");
background-repeat: no-repeat;
background-size: 30%;
height: 100%;

View File

@@ -1,11 +1,14 @@
// Override any Bootstrap variables or add custom ones here
@icon-font-path: "../fonts";
@fa-font-path: "../fonts";
@font-path: "../dist/fonts";
@fa-font-path: "../../../dist/fonts";
@icon-font-path: "../../../dist/fonts/";
@img-path: "../dist/img";
// remove this when https://github.com/patternfly/patternfly/pull/363 is resolved
@navbar-pf-alt-bg-img: url("../../../node_modules/patternfly/dist/img/bg-navbar-pf-alt.svg");
@header-height: 86px;
@login-bg-color: #f1f1f1;
@img-bg-login: "bg-login.png";
@img-bg-login-2: "bg-login-2.png";

View File

@@ -1,24 +0,0 @@
module.exports = {
devtool: 'source-map',
output: {
filename: 'tripleo_ui_tempstorage_worker.js',
sourceMapFilename: 'tripleo_ui_tempstorage_worker.js.map'
},
module: {
loaders: [
{
test: /\.js$/,
include: /src\/js\/workers/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'stage-0', 'react']
}
}
]
},
node: {
fs: 'empty',
net: 'empty',
tls: 'empty'
}
};

View File

@@ -1,25 +1,91 @@
module.exports = {
devtool: 'source-map',
entry: __dirname + '/src/js/index.js',
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: 'tripleo_ui.js',
sourceMapFilename: '../js/tripleo_ui.js.map'
sourceMapFilename: 'tripleo_ui.js.map'
},
module: {
loaders: [
// Javascript
{
test: /\.js$/,
include: /src/,
exclude: /src\/js\/workers/,
loader: 'babel-loader',
loader: 'babel'
},
// Shared Workers
{
test: /\.js$/,
include: /src\/js\/workers/,
loader: 'shared-worker!babel'
},
// Images
{
test: /\.(png|jpg|gif)(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url-loader',
query: {
presets: ['es2015', 'stage-0', 'react']
limit: 8192, // inline base64 URLs for <=8k images, direct URLs for the rest
name: '[name].[ext]'
}
},
// Fonts and svg images
{
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url',
query: {
limit: 8192,
mimetype: 'application/font-woff',
name: '[name].[ext]'
}
},
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url',
query: {
limit: 8192,
mimetype: 'application/octet-stream',
name: '[name].[ext]'
}
},
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file',
query: { name: '[name].[ext]' }
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url',
query: {
limit: 8192,
mimetype: 'image/svg+xml',
name: '[name].[ext]'
}
},
// Plain CSS files
{
test: /\.css$/,
loader: 'style!css'
},
// Less
{
test: /\.less$/,
loader: 'style!css!less?sourceMap'
}
]
},
node: {
fs: 'empty',
net: 'empty',
tls: 'empty'
devServer: {
contentBase: './dist',
port: 3000,
colors: true,
historyApiFallback: true,
inline: true
}
};