Better webpack config

This commit is contained in:
Lucas Verney 2016-07-25 23:22:44 +02:00
parent 767fd0f7d1
commit 136fb59ed5
17 changed files with 1606 additions and 481 deletions

View File

@ -3,6 +3,13 @@ module.exports = {
"browser": true, "browser": true,
"es6": true "es6": true
}, },
"globals": {
"$": false,
"jQuery": false,
"process": false,
"module": true,
"require": false
},
"extends": "eslint:recommended", "extends": "eslint:recommended",
"installedESLint": true, "installedESLint": true,
"parserOptions": { "parserOptions": {

7
.stylelintrc Normal file
View File

@ -0,0 +1,7 @@
{
"extends": "stylelint-config-standard",
"rules": {
"indentation": 4,
},
"defaultSeverity": "error"
}

View File

@ -16,7 +16,8 @@ to the correct URL :)
The supported browsers should be: The supported browsers should be:
* `IE >= 9` (previous versions of IE are no longer supported by Microsoft) * `IE >= 9` (previous versions of IE are no longer supported by Microsoft)
* Any recent version of any other browser. * Any last three versions of major browsers (> 1% net share).
* No support provided for Opera Mini.
If you experience any issue, please report :) If you experience any issue, please report :)

12
TODO
View File

@ -4,13 +4,25 @@
8. Search 8. Search
9. Discover 9. Discover
# CSS
* Sidebar responsiveness
* Songs on iPhone 5
* Set sidebar .active
* /artist/:id and /album/:id arts in responsive view
* Scroll horizontal sidebar
* Move CSS in modules
## Global UI ## Global UI
* What happens when JS is off? * What happens when JS is off?
=> https://www.allantatter.com/react-js-and-progressive-enhancement/ => https://www.allantatter.com/react-js-and-progressive-enhancement/
* Back button?
## Miscellaneous ## Miscellaneous
* See TODOs in the code * See TODOs in the code
* https://facebook.github.io/immutable-js/ ? * https://facebook.github.io/immutable-js/ ?
* Web workers? * Web workers?
* Accessibility and semantics * Accessibility and semantics
* Uncaught TypeError: this.props.tracks.forEach is not a function
=> Be more robust, after, getHostNode is null

View File

@ -2,8 +2,6 @@ import React, { Component, PropTypes } from "react";
import { AlbumRow } from "./Album"; import { AlbumRow } from "./Album";
// TODO: Songs without associated album
export default class Artist extends Component { export default class Artist extends Component {
render () { render () {
var albumsRows = []; var albumsRows = [];

View File

@ -2,9 +2,9 @@ import React, { Component, PropTypes } from "react";
export class LoginForm extends Component { export class LoginForm extends Component {
constructor (props) { constructor (props) {
super(props) super(props);
this.handleSubmit = this.handleSubmit.bind(this) this.handleSubmit = this.handleSubmit.bind(this);
} }
setError (formGroup, error) { setError (formGroup, error) {
@ -30,11 +30,11 @@ export class LoginForm extends Component {
hasError |= this.setError(this.refs.endpointFormGroup, !endpoint); hasError |= this.setError(this.refs.endpointFormGroup, !endpoint);
if (!hasError) { if (!hasError) {
this.props.onSubmit(username, password, endpoint, rememberMe) this.props.onSubmit(username, password, endpoint, rememberMe);
} }
} }
componentDidUpdate (prevProps) { componentDidUpdate () {
if (this.props.error) { if (this.props.error) {
$(this.refs.loginForm).shake(3, 10, 300); $(this.refs.loginForm).shake(3, 10, 300);
this.setError(this.refs.usernameFormGroup, this.props.error); this.setError(this.refs.usernameFormGroup, this.props.error);

1
app/dist/fix.ie9.js.map vendored Normal file

File diff suppressed because one or more lines are too long

8
app/dist/index.js vendored

File diff suppressed because one or more lines are too long

1
app/dist/index.js.map vendored Normal file

File diff suppressed because one or more lines are too long

1834
app/dist/style.css vendored

File diff suppressed because it is too large Load Diff

1
app/dist/style.css.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"sources":[],"names":[],"mappings":"","file":"style.css","sourceRoot":""}

View File

@ -15,44 +15,55 @@
color: white; color: white;
border-right: 1px solid #eee; border-right: 1px solid #eee;
} }
/* Sidebar elements */ /* Sidebar elements */
.sidebar a { .sidebar a {
color: white; color: white;
} }
.sidebar h1 { .sidebar h1 {
margin: 0; margin: 0;
margin-bottom: 20px; margin-bottom: 20px;
} }
.sidebar h1 img { .sidebar h1 img {
height: 46px; height: 46px;
} }
.sidebar h1 a { .sidebar h1 a {
text-decoration: none; text-decoration: none;
} }
/* Sidebar navigation */ /* Sidebar navigation */
.nav-sidebar { .nav-sidebar {
margin-right: -21px; /* 20px padding + 1px border */ margin-right: -21px; /* 20px padding + 1px border */
margin-bottom: 20px; margin-bottom: 20px;
margin-left: -20px; margin-left: -20px;
} }
.nav-sidebar > li > a { .nav-sidebar > li > a {
padding-right: 20px; padding-right: 20px;
padding-left: 20px; padding-left: 20px;
} }
.nav-sidebar .nav-sidebar { .nav-sidebar .nav-sidebar {
margin-bottom: 0; /* No margin bottom for nested nav-sidebar. */ margin-bottom: 0; /* No margin bottom for nested nav-sidebar. */
} }
.nav-sidebar > .active > a, .nav-sidebar > .active > a,
.nav-sidebar > .active > a:hover, .nav-sidebar > .active > a:hover,
.nav-sidebar > .active > a:focus, .nav-sidebar > .active > a:focus,
.nav>li>a:hover { .nav > li > a:hover,
.nav > li > a:focus {
color: #fff; color: #fff;
background-color: #222; background-color: #222;
} }
.icon-navbar { .icon-navbar {
background-color: #555; background-color: #555;
font-size: 1.25em; font-size: 1.25em;
} }
.icon-navbar-nav { .icon-navbar-nav {
display: inline-block; display: inline-block;
float: none; float: none;
@ -60,13 +71,13 @@
text-align: center; text-align: center;
} }
/* /*
* Main content * Main content
*/ */
.main-panel { .main-panel {
padding: 20px; padding: 20px;
} }
@media (min-width: 768px) { @media (min-width: 768px) {
.main-panel { .main-panel {
padding-right: 40px; padding-right: 40px;
@ -74,29 +85,30 @@
} }
} }
/* /*
* Filtering field * Filtering field
*/ */
div.filter { div.filter {
margin-bottom: 34px; margin-bottom: 34px;
} }
.filter-legend { .filter-legend {
text-align: right; text-align: right;
line-height: 34px; line-height: 34px;
} }
@media (max-width: 767px) { @media (max-width: 767px) {
.filter-legend { .filter-legend {
text-align: center; text-align: center;
} }
} }
@media (min-width: 767px) { @media (min-width: 767px) {
.filter .form-group { .filter .form-group {
width: 75%; width: 75%;
} }
} }
/* /*
* Placeholder dashboard ideas * Placeholder dashboard ideas
*/ */
@ -104,22 +116,24 @@ div.filter {
margin-bottom: 30px; margin-bottom: 30px;
text-align: center; text-align: center;
} }
.placeholders h4 { .placeholders h4 {
margin-bottom: 0; margin-bottom: 0;
} }
.placeholder img:hover { .placeholder img:hover {
transform: scale(1.1); transform: scale(1.1);
cursor: pointer; cursor: pointer;
} }
/** /**
* Pager * Pager
*/ */
.pagination-nav { .pagination-nav {
text-align: center; text-align: center;
} }
.pagination>li>span {
.pagination > li > span {
cursor: pointer; cursor: pointer;
} }
@ -129,6 +143,7 @@ div.filter {
.login h1 img { .login h1 img {
height: 46px; height: 46px;
} }
@media (max-width: 767px) { @media (max-width: 767px) {
.login .submit { .login .submit {
text-align: center; text-align: center;
@ -142,12 +157,11 @@ div.filter {
.art { .art {
display: inline-block; display: inline-block;
border-radius: 50%; border-radius: 50%;
margin-bottom: .5em; margin-bottom: 0.5em;
width: 75%; width: 75%;
height: auto; height: auto;
} }
.albumRow { .albumRow {
margin-top: 30px; margin-top: 30px;
} }

View File

@ -1,4 +1,4 @@
import React, { Component } from "react"; import { Component } from "react";
import { bindActionCreators } from "redux"; import { bindActionCreators } from "redux";
import { connect } from "react-redux"; import { connect } from "react-redux";
@ -16,11 +16,8 @@ export class LogoutPage extends Component {
} }
} }
const mapStateToProps = (state) => ({
});
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
actions: bindActionCreators(actionCreators, dispatch) actions: bindActionCreators(actionCreators, dispatch)
}); });
export default connect(mapStateToProps, mapDispatchToProps)(LogoutPage); export default connect(null, mapDispatchToProps)(LogoutPage);

View File

@ -1,7 +1,5 @@
#!/bin/sh #!/bin/sh
# TODO: Rebuild only if needed
# Get against which ref to diff # Get against which ref to diff
if git rev-parse --verify HEAD >/dev/null 2>&1 if git rev-parse --verify HEAD >/dev/null 2>&1
then then
@ -26,21 +24,6 @@ then
fi fi
# ESLint modified files
if [ -e "./node_modules/eslint/bin/eslint.js" ]
then
ESLINT="node ./node_modules/eslint/bin/eslint.js"
elif hash eslint
then
ESLINT="eslint"
else
exit "You should install ESLint."
fi
echo "Running ESLint on your code…"
$ESLINT $js_files
# Run webpack # Run webpack
if [ -e "./node_modules/webpack/bin/webpack.js" ] if [ -e "./node_modules/webpack/bin/webpack.js" ]
then then

View File

@ -35,15 +35,20 @@
"babel-loader": "^6.2.4", "babel-loader": "^6.2.4",
"babel-preset-react": "^6.11.1", "babel-preset-react": "^6.11.1",
"css-loader": "^0.23.1", "css-loader": "^0.23.1",
"doiuse": "^2.4.1",
"eslint": "^3.1.1", "eslint": "^3.1.1",
"eslint-loader": "^1.4.1",
"eslint-plugin-react": "^5.2.2", "eslint-plugin-react": "^5.2.2",
"extract-text-webpack-plugin": "^1.0.1", "extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.9.0", "file-loader": "^0.9.0",
"postcss": "^5.1.0", "postcss": "^5.1.0",
"postcss-loader": "^0.9.1", "postcss-loader": "^0.9.1",
"postcss-reporter": "^1.4.1",
"precss": "^1.4.0", "precss": "^1.4.0",
"redux-logger": "^2.6.1", "redux-logger": "^2.6.1",
"style-loader": "^0.13.1", "style-loader": "^0.13.1",
"stylelint": "^7.0.3",
"stylelint-config-standard": "^11.0.0",
"url-loader": "^0.5.7", "url-loader": "^0.5.7",
"webpack": "^1.13.1" "webpack": "^1.13.1"
} }

View File

@ -2,8 +2,12 @@ var path = require("path");
var webpack = require("webpack"); var webpack = require("webpack");
var ExtractTextPlugin = require("extract-text-webpack-plugin"); var ExtractTextPlugin = require("extract-text-webpack-plugin");
var postcssReporter = require("postcss-reporter");
var doiuse = require("doiuse");
var stylelint = require("stylelint");
var precss = require("precss"); var precss = require("precss");
var autoprefixer = require("autoprefixer"); var autoprefixer = require("autoprefixer");
var browsers = ["ie >= 9", "> 1%", "last 3 versions", "not op_mini all"];
module.exports = { module.exports = {
entry: { entry: {
@ -18,6 +22,13 @@ module.exports = {
}, },
module: { module: {
preLoaders: [
{
test: /\.jsx?$/,
loader: "eslint-loader?{failOnError: true}",
exclude: /node_modules/
}
],
loaders: [ loaders: [
// Handle JS/JSX files // Handle JS/JSX files
{ {
@ -26,10 +37,17 @@ module.exports = {
loaders: ["babel"], loaders: ["babel"],
include: __dirname include: __dirname
}, },
// Do not postcss vendor modules
{ {
test: /\.css$/, test: /\.css$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!postcss-loader") loader: ExtractTextPlugin.extract("style-loader", "css-loader!postcss-loader")
}, },
{
test: /\.css$/,
exclude: /app/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader")
},
{ {
test: /\.less$/, test: /\.less$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader") loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader")
@ -66,9 +84,7 @@ module.exports = {
], ],
postcss: function () { postcss: function () {
return [precss, autoprefixer({ return [doiuse({ browsers: browsers }), stylelint, precss, autoprefixer({ browsers: browsers }), postcssReporter({ throwError: true, clearMessages: true })];
browsers: ["last 3 versions"]
})];
}, },
resolve: { resolve: {

View File

@ -3,7 +3,6 @@ var config = require("./webpack.config.base.js");
// Report first error as hard error // Report first error as hard error
config.bail = true; config.bail = true;
// Switch to debug mode
config.debug = false; config.debug = false;
// Do not capture timing information for each module // Do not capture timing information for each module
config.profile = false; config.profile = false;
@ -11,6 +10,7 @@ config.profile = false;
config.devtool = "#source-map"; config.devtool = "#source-map";
config.plugins = config.plugins.concat([ config.plugins = config.plugins.concat([
new webpack.NoErrorsPlugin(),
new webpack.optimize.OccurenceOrderPlugin(true), new webpack.optimize.OccurenceOrderPlugin(true),
new webpack.optimize.DedupePlugin(), new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({ new webpack.optimize.UglifyJsPlugin({