Skip to content

Commit

Permalink
Merge pull request #7 from mtrifilo/upgrade-dependencies
Browse files Browse the repository at this point in the history
Upgrade dependencies for v2.0.0
  • Loading branch information
mtrifilo authored Dec 31, 2017
2 parents 25f8ec8 + 90ce548 commit cf1686c
Show file tree
Hide file tree
Showing 32 changed files with 3,013 additions and 2,008 deletions.
12 changes: 3 additions & 9 deletions .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,12 @@
"env": {
"test": {
"plugins": [
"transform-es2015-modules-commonjs",
"transform-object-rest-spread"
"transform-es2015-modules-commonjs"
]
},
"server": {
"plugins": [
"transform-es2015-modules-commonjs",
"transform-object-rest-spread"
]
"plugins":
"transform-es2015-modules-commonjs"
}
// "production": {
// "plugins": ["transform-es2015-modules-commonjs"]
// }
}
}
9 changes: 7 additions & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@
"parser": "babel-eslint",
"extends": [
"standard",
"standard-react"
"standard-react",
"plugin:jest/recommended"
],
"rules": {
"object-curly-spacing": [
"error",
"always"
]
},
"plugins": ["jest"],
"env": {
"jest/globals": true
}
}
}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ data/*
config.json
public/*
!public/.gitkeep
.vscode/*
.vscode
coverage
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: node_js
node_js:
- "6"
- "8"
env:
- CXX=g++-4.8
addons:
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## 2.0.0 (1/31/2017) :tada:

Many of the core libraries and tools have had major releases, as they should, so this major release is to account for any breaking changes they've introduced. Most of the breakage occured with the Bootstrap upgrade from alpha to beta 3, but Bootstrap 4 should remain much more stable from beta to release. The rest of the updates were relatively painless. Hello React 16!

Major changes:

- React 15 -> React 16
- Webpack 2 -> Webpack 3
- Bootstrap 4 alpha -> Bootstrap 4 beta
- Implements Jest more fully with new lint rules and supporting dependencies
- Upgrade TravisCI's Node environment from 6 to 8
- All other dependencies upgraded, some including major version bumps
- various refactors and cleanup

## 1.0.0 (05/19/2017)

This marks the first release of the boilerplate! :tada:
Expand Down
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

### [Live Demo](https://react-ssr-boilerplate.matttrifilo.com/)

A minimalistic boiler plate with everything you need to get a server side rendered React application up and running FAST.
A minimalistic boilerplate with everything you need to get a server side rendered React application up and running FAST.

This is meant to be an alternative starter project for Free Code Camp full stack application projects. It's not officially affiliated with Free Code Camp.
This was originally meant to be an alternative starter project for Free Code Camp full stack application projects. It's not officially affiliated with Free Code Camp.

Many of the implementations here are opinionated, so feel free to refactor them, or gut them, in anyway you see fit to work for your way of thinking and your use case.

## Batteries Included :battery:

You get everything you need to build out a full stack application with:
You get everything you need to build out a full stack application with:
- React
- React Router 4
- Redux
Expand All @@ -22,22 +22,22 @@ You get everything you need to build out a full stack application with:
- Mongoose
- Passport

Out of the box, the boilerplate comes with a few views, and working local and OAuth authentication to get you going.
Out of the box, the boilerplate comes with a few views, and working local and OAuth authentication to get you going.

The React application itself is what is called a universal (formerly "isomorphic") JavaScript application. This means that on the server, React will render its component tree into HTML markup as a big string, and pass it down to the browser. Instead of the browser having to wait for a JavaScript bundle with the React application, it can simply show the HTML it's getting right away while the JavaScript bundles download. Once the React application code finishes downloading to the client, the JavaScript will be able to handle user interactions without needing to re-render the markup that already arrived pre-rendered from the server. This has huge performance wins for users with slow connections and is becoming a common way serve production React applications, in addition to other frameworks like Angular 2 and 4.
The React application itself is what is called a universal (formerly "isomorphic") JavaScript application. This means that on the server, React will render its component tree into HTML markup as a big string, and pass it down to the browser. Instead of the browser having to wait for a JavaScript bundle with the React application, it can simply show the HTML it's getting right away while the JavaScript bundles download. Once the React application code finishes downloading to the client, the JavaScript will be able to handle user interactions without needing to re-render the markup that already arrived pre-rendered from the server. This has huge performance wins for users with slow connections and is becoming a common way serve production React applications, in addition to other frameworks like Angular and Vue.

### Why another boilerplate? :dancers:

Free Code Camp encourages students to use a boilerplate collection called `Clementine.js`, which is very powerful and easy to set up. It has great documentation and tutorials so it's the way to go if you're new to building full stack applications.

This boilerplate is meant to be an alternative for students who want to build their full stack application projects using modern tools from the React ecosystem, with a project structure that is tailored to using React and Redux.
This boilerplate is meant to be an alternative for anyone who wants to build full stack applications using modern tools from the React ecosystem, with a project structure that is tailored to using React and Redux.

There are many mature React boilerplates out their with dozens (or hundreds!) of smart, experienced developers contributing to them all the time, but a lot of them are overly complex for just building a basic full stack application in my opinion. This boilerplate isn't meant to address every use case, or be optimally polished for production ready apps. It's meant to be easy to understand and extend, while encouraging good habits for a good user and developer experience.
There are many mature React boilerplates out their with dozens (even hundreds!) of smart, experienced developers contributing to them all the time, but a lot of them are overly complex for just building a basic full stack application in my opinion. This boilerplate isn't meant to address every use case, or to be fully production ready. It's meant to be easy to understand and extend, while encouraging good habits for a good user and developer experience.

I encourage you to learn these technologies deeply before using this for a project, as it is fairly complex. I'll be working on documenting and commenting every aspect of this boilerplate to make it as clear and extendable as possible, but you'll get much more out of it if you have a solid understanding of how the underlying technologies like React, Redux, React Router 4, and Express all work and work together. Server side rendering has gotten easier over time, but that's another level of complexity that needs to be accounted for when adding features.
I recommend that you learn these technologies deeply before using this for a project, as it is fairly complex. I'll be working on documenting and commenting every aspect of this boilerplate to make it as clear and extendable as possible, but you'll get much more out of it if you have a solid understanding of how the underlying technologies like React, Redux, React Router 4, Mongo, and Express all work and work together. Server side rendering has gotten easier, but it's another level of complexity that needs to be accounted for when adding features.

That said, I think it's beneficial to challenge yourself with modern tools you'll likely find at companies using React every day. If you can master these technologies, you'll be in great shape build whatever you can dream up.

That said, I think it's beneficial to challenge yourself with modern tools you'll likely find at companies using React every day.

### Roadmap :milky_way:

* Thorough documentation
Expand Down Expand Up @@ -75,14 +75,14 @@ Here are the constants it contains:
// The full domain for Passport to use in the GitHub strategy.
// For actual DNS names, the port will not be necessary
"domain": "http://localhost:4000",
// If you're running MongoDB locally, this address will work fine with
// If you're running MongoDB locally, this address will work fine with
// the mongo NPM script during development.
"mongoUriDev": "mongodb://localhost:27017/react-ssr-boiler",
// You can set up a free MongoDB instance at mlab.com
"mongoUriProduction": "ENTER_YOUR_PRODUCTION_MONGO_URI_FROM_MLAB_OR_ELSEWHERE",
// A complex string to be used for creating and verifying JSON Web Tokens
"jwtSecret": "PickAComplexString1337",
// Your app's GitHub credentials.
// Your app's GitHub credentials.
// Go to github.com, log in, go to settings, then scroll down to "developer settings"
// and you'll find "OAuth Applications". Go there to register your new application.
// The callback URL will be `${domain}/api/login/github/callback`
Expand Down
20 changes: 20 additions & 0 deletions client/auth/__test__/setTokenHeaders.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const axios = require('axios')

const setTokenToHeaders = require('../../auth/setTokenToHeaders')

afterEach(() => {
if (axios.defaults.headers.common['Authorization']) {
delete axios.defaults.headers.common['Authorization']
}
})

test('with token: should set Authorization header with the token', () => {
setTokenToHeaders('testToken')
expect(axios.defaults.headers.common['Authorization']).toBe('Bearer testToken')
})

test('without token: should delete token if present', () => {
axios.defaults.headers.common['Authorization'] = 'testToken'
setTokenToHeaders()
expect(axios.defaults.headers.common['Authorization']).toBeUndefined()
})
2 changes: 1 addition & 1 deletion client/auth/setTokenToHeaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const axios = require('axios')
function setTokenToHeaders (token) {
if (token) {
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`
} else {
} else if (axios.defaults.headers.common['Authorization']) {
delete axios.defaults.headers.common['Authorization']
}
}
Expand Down
40 changes: 25 additions & 15 deletions client/components/Account/AccountSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,24 @@ class AccountSettings extends Component {

onChangeHandler = evt => {
this.setState({ [evt.target.name]: evt.target.value })
};
}

onBlurHandler = evt => {
if (evt.target.name === 'newUsername') {
this.setValidationError(validateNewUsername(this.state.newUsername))
if (this.state.newUsername !== this.props.username && this.state.newUsername !== '') {
if (
this.state.newUsername !== this.props.username &&
this.state.newUsername !== ''
) {
this.props.dispatchCheckUsernameUniqueness(this.state.newUsername)
}
}
if (evt.target.name === 'newEmail') {
this.setValidationError(validateNewEmail(this.state.newEmail))
if (this.state.newEmail !== this.props.email && this.state.newEmail !== '') {
if (
this.state.newEmail !== this.props.email &&
this.state.newEmail !== ''
) {
this.props.dispatchCheckEmailUniqueness(this.state.newEmail)
}
}
Expand All @@ -76,7 +82,7 @@ class AccountSettings extends Component {
)
)
}
};
}

setValidationError = validationResult => {
// set the validtion result to state
Expand All @@ -88,7 +94,7 @@ class AccountSettings extends Component {
this.setState({ validationErrors: newValidationErrors }, () => {
this.checkFormValidity()
})
};
}

checkFormValidity = () => {
const {
Expand All @@ -106,7 +112,9 @@ class AccountSettings extends Component {
identifiersValid = false
}
if (
currentPassword !== '' || newPassword !== '' || confirmNewPassword !== ''
currentPassword !== '' ||
newPassword !== '' ||
confirmNewPassword !== ''
) {
passwordValid = false
}
Expand All @@ -117,12 +125,12 @@ class AccountSettings extends Component {
password: passwordValid
}
})
};
}

onClickDeleteAccount = evt => {
evt.preventDefault()
this.props.dispatchDeleteUserAccount()
};
}

componentDidMount () {
this.props.dispatchGetCurrentUser()
Expand Down Expand Up @@ -154,19 +162,20 @@ class AccountSettings extends Component {
return (
<div>
<h1 className='text-center page-title'>Account Settings</h1>
{this.props.gitHubToken
? <GitHubAccountSettings
{this.props.gitHubToken ? (
<GitHubAccountSettings
newUsername={this.state.newUsername}
onChangeHandler={this.onChangeHandler}
onBlurHandler={this.onBlurHandler}
dispatchChangeGitHubUsername={
this.props.dispatchChangeGitHubUsername
}
this.props.dispatchChangeGitHubUsername
}
validationErrors={this.state.validationErrors}
setValdiationError={this.setValidationError}
isValid={this.state.isValid.identifiers}
/>
: <LocalAccountSettings
/>
) : (
<LocalAccountSettings
newUsername={this.state.newUsername}
newEmail={this.state.newEmail}
username={this.props.username}
Expand All @@ -179,7 +188,8 @@ class AccountSettings extends Component {
validationErrors={this.state.validationErrors}
setValdiationError={this.setValidationError}
isValid={this.state.isValid}
/>}
/>
)}
<DeleteAccountModal onClickDeleteAccount={this.onClickDeleteAccount} />
</div>
)
Expand Down
2 changes: 1 addition & 1 deletion client/components/Account/GitHubAccountSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class GitHubAccountSettings extends Component {
this.props.dispatchChangeGitHubUsername({
newUsername: this.props.newUsername
})
};
}

render () {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,13 @@ class ChangeIdentifierForm extends Component {

if (!isEmpty(userDataChanges)) {
console.log('userDataChanges', userDataChanges)
this.props.dispatchChangeUserIdentifiers(
userDataChanges,
this.props.user
)
this.props.dispatchChangeUserIdentifiers(userDataChanges, this.props.user)
} else {
console.log('no changes to submit')
// dispatch flashMessage to inform the user that there
// are no changes to submit
}
};
}

render () {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class ChangePasswordForm extends Component {
return this.props.setValidationError(validation.validationErrors)
}
this.props.dispatchChangeUserPassword(passwordData)
};
}

render () {
return (
Expand Down
4 changes: 3 additions & 1 deletion client/components/BrowserEntry.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ import '../../node_modules/bootstrap/dist/js/bootstrap.js'
import '../../node_modules/bootstrap/dist/css/bootstrap.css'
import './main.css'

ReactDOM.render(<App />, document.getElementById('app'))
window.addEventListener('DOMContentLoaded', () => {
ReactDOM.hydrate(<App />, document.getElementById('app'))
})
4 changes: 2 additions & 2 deletions client/components/Common/FlashMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ class FlashMessage extends Component {
this.setState({ display: false })
}, 1500)
}
};
}

componentDidMount = () => {
setTimeout(() => {
this.setState({ display: true })
}, 50)
};
}

render () {
this.showMessage()
Expand Down
4 changes: 2 additions & 2 deletions client/components/Common/Input.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ const Input = ({
name={name}
onChange={onChange}
onBlur={onBlur}
className='form-control'
className={classNames('form-control', { 'is-invalid': validationError })}
/>
{validationError &&
<div className='form-control-feedback'>
<div className='invalid-feedback'>
{validationError}
</div>}
</div>
Expand Down
31 changes: 31 additions & 0 deletions client/components/Common/ShowIfLoggedOut.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { Redirect } from 'react-router'
import { array, bool } from 'prop-types'

class ShowIfLoggedOut extends Component {
render () {
if (this.props.isAuthenticated) {
return <Redirect to='/' />
}

if (this.props.isAuthenticated !== false) {
return null
}

return <div>{this.props.children}</div>
}
}

ShowIfLoggedOut.propTypes = {
children: array.isRequired,
isAuthenticated: bool.isRequired
}

const mapStateToProps = state => {
return {
isAuthenticated: state.user.isAuthenticated
}
}

export default connect(mapStateToProps)(ShowIfLoggedOut)
Loading

0 comments on commit cf1686c

Please sign in to comment.