Skip to content
This repository has been archived by the owner on May 6, 2024. It is now read-only.

ref: Update to latest react, redux, and various supporting libs #228

Merged
merged 14 commits into from
Nov 13, 2019
Merged
21 changes: 0 additions & 21 deletions .babelrc

This file was deleted.

1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
/node_modules/
/config/
/scripts/
babel.config.js
6 changes: 5 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ env:
global:
- NODE_ENV=production
- PIP_DISABLE_PIP_VERSION_CHECK=on
- JEST_JUNIT_OUTPUT_DIR=.artifacts
- JEST_JUNIT_OUTPUT_NAME=jest.junit.xml
- JEST_JUNIT_INCLUDE_CONSOLE_OUTPUT=true
- JEST_JUNIT_ADD_FILE_ATTRIBUTE=true
install:
- curl -sSL https://raw.githubusercontent.com/sdispater/poetry/0.12.10/get-poetry.py | python
- curl -sSLf https://get.volta.sh | bash
Expand All @@ -25,7 +29,7 @@ script:
- PATH=$HOME/.poetry/bin:$PATH PATH=node_modules/.bin:$PATH pre-commit run -a -v
- PATH=$HOME/.poetry/bin:$PATH poetry run py.test tests -v --cov . --cov-report="xml:.artifacts/coverage.xml" --junit-xml=".artifacts/pytest.junit.xml"
- node_modules/.bin/webpack --json > .artifacts/webpack-stats.json
- JEST_JUNIT_OUTPUT=.artifacts/jest.junit.xml yarn test --ci --reporters=default --reporters=jest-junit
- JEST_JUNIT_OUTPUT_DIR=.artifacts JEST_JUNIT_OUTPUT_NAME=jest.junit.xml yarn test --ci --reporters=default --reporters=jest-junit
after_script:
- npm install -g @zeus-ci/cli
- $(npm bin -g)/zeus upload -t "application/x-junit+xml" .artifacts/*.junit.xml
Expand Down
49 changes: 49 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
module.exports = function(api) {
api.cache.using(() => process.env.NODE_ENV === 'development');

return {
presets: ['@babel/react', '@babel/env'],
plugins: [
'emotion',
'lodash',
'babel-plugin-idx',
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-proposal-object-rest-spread',
'@babel/plugin-transform-runtime',
// NOTE: The order of the decorator and class-property plugins is important
// here. Decorators must be processed first before class properties, see:
// https://babeljs.io/docs/en/plugins#plugin-ordering
['@babel/plugin-proposal-decorators', {legacy: true}],
['@babel/plugin-proposal-class-properties', {loose: true}]
],
env: {
production: {
plugins: [
[
'transform-react-remove-prop-types',
{
mode: 'remove', // remove from bundle
removeImport: true, // removes `prop-types` import statements
classNameMatchers: [
'SelectField',
'FormField',
'AsyncComponent',
'AsyncView'
],
additionalLibraries: [/app\/sentryTypes$/]
}
]
]
},
development: {
plugins: [
['emotion', {sourceMap: true, autoLabel: true}],
'@babel/plugin-transform-react-jsx-source'
]
},
test: {
plugins: [['emotion', {autoLabel: true}], 'dynamic-import-node']
}
}
};
};
71 changes: 43 additions & 28 deletions config/jest/testStubs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,51 @@ import sinon from 'sinon';
import thunk from 'redux-thunk';
import PropTypes from 'prop-types';
import configureStore from 'redux-mock-store';
import {createMount, createShallow} from 'enzyme-context';
import {routerContext} from 'enzyme-context-react-router-3';
import {reduxContext} from 'enzyme-context-redux';

const mockStore = configureStore([thunk]);

const createRouter = () => ({
push: sinon.spy(),
replace: sinon.spy(),
go: sinon.spy(),
goBack: sinon.spy(),
goForward: sinon.spy(),
setRouteLeaveHook: sinon.spy(),
isActive: sinon.spy(),
createHref: sinon.spy()
});

const createStore = state =>
// TODO(dcramer): It'd be nice if this could be auto generated
mockStore({
auth: {isAuthenticated: null, user: null},
builds: {
items: [],
loaded: false,
links: {}
},
repos: {
items: [],
loaded: false
},
...state
});

const plugins = {
store: reduxContext({
createStore
}),
history: routerContext()
};

window.TestStubs = {
mount: createMount(plugins),
shallow: createShallow(plugins),
// react-router's 'router' context
router: () => ({
push: sinon.spy(),
replace: sinon.spy(),
go: sinon.spy(),
goBack: sinon.spy(),
goForward: sinon.spy(),
setRouteLeaveHook: sinon.spy(),
isActive: sinon.spy(),
createHref: sinon.spy()
}),
router: createRouter,

location: () => ({
query: {},
Expand All @@ -26,33 +56,18 @@ window.TestStubs = {
routerContext: (location, router) => ({
context: {
location: location || TestStubs.location(),
router: router || TestStubs.router()
router: router || createRouter()
},
childContextTypes: {
router: PropTypes.object,
location: PropTypes.object
}
}),

store: state =>
// TODO(dcramer): It'd be nice if this could be auto generated
mockStore({
auth: {isAuthenticated: null, user: null},
builds: {
items: [],
loaded: false,
links: {}
},
repos: {
items: [],
loaded: false
},
...state
}),
store: createStore,

storeContext: store => ({
context: {
store: store || TestStubs.store()
store: store || createStore()
},
childContextTypes: {
store: PropTypes.object
Expand Down
126 changes: 2 additions & 124 deletions config/webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
'use strict';

const autoprefixer = require('autoprefixer');
const path = require('path');
const webpack = require('webpack');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const ManifestPlugin = require('webpack-manifest-plugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getClientEnvironment = require('./env');
Expand All @@ -20,9 +18,6 @@ const publicUrl = 'static';
// Get environment variables to inject into our app.
const env = getClientEnvironment(publicUrl);

// Note: defined here because it will be used more than once.
const cssFilename = 'css/[name].css';

const isProd = env.stringified['process.env'].NODE_ENV === '"production"';

function getPlugins() {
Expand Down Expand Up @@ -64,13 +59,6 @@ function getPlugins() {
// You can remove this if you don't use Moment.js:
plugins.push(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/));

// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
plugins.push(
new ExtractTextPlugin({
filename: cssFilename
})
);

// Generate a manifest file which contains a mapping of all asset filenames
// to their corresponding output file so that tools can pick it up without
// having to parse `index.html`.
Expand All @@ -80,68 +68,12 @@ function getPlugins() {
})
);

// this assumes your vendor imports exist in the node_modules directory
plugins.push(
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: Infinity
// minChunks: module => module.context && module.context.indexOf('node_modules') !== -1
})
);

// Minify the code.
isProd &&
plugins.push(
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
// Disabled because of an issue with Uglify breaking seemingly valid code:
// https://github.com/facebookincubator/create-react-app/issues/2376
// Pending further investigation:
// https://github.com/mishoo/UglifyJS2/issues/2011
comparisons: false
},
output: {
comments: false,
// Turned on because emoji and regex is not minified properly using default
// https://github.com/facebookincubator/create-react-app/issues/2488
ascii_only: true
},
sourceMap: true
})
);
return plugins;
}

function getEntry() {
let entry = {};
// We ship a few polyfills by default:
entry.polyfills = require.resolve('./polyfills');
// Finally, this is your app's code:
// We include the app code last so that if there is a runtime error during
// initialization
entry.app = paths.appIndexJs;
entry.vendor = [
'classnames',
'lodash',
'marked',
'dompurify',
'moment',
'react',
'react-chartjs-2',
'react-gravatar',
'react-dom',
'react-document-title',
'react-loadable',
'react-redux',
'react-router',
'react-select',
'react-syntax-highlighter',
'react-transition-group',
'redux',
'redux-thunk',
'styled-components'
];
return entry;
}

Expand Down Expand Up @@ -255,61 +187,12 @@ module.exports = {
/\.json$/,
/\.bmp$/,
/\.gif$/,
/\.jpe?g$/,
/\.png$/
/\.jpe?g$/
],
loader: require.resolve('file-loader'),
options: {
name: 'media/[name].[ext]'
}
},
// "url" loader works like "file" loader except that it embeds assets
// smaller than specified limit in bytes as data URLs to avoid requests.
// A missing `test` is equivalent to a match.
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'media/[name].[ext]'
}
},
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
// In production, we use a plugin to extract that CSS to a file, but
// in development "style" loader enables hot editing of CSS.
{
test: /\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1
}
},
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9' // React doesn't support IE8 anyway
],
flexbox: 'no-2009'
})
]
}
}
]
}
// ** STOP ** Are you adding a new loader?
// Remember to add the new extension(s) to the "file" loader exclusion list.
Expand All @@ -324,10 +207,5 @@ module.exports = {
net: 'empty',
tls: 'empty'
},
// Turn off performance hints during development because we don't do any
// splitting or minification in interest of speed. These warnings become
// cumbersome.
performance: {
hints: isProd ? 'warning' : false
}
mode: process.env.NODE_ENV ? process.env.NODE_ENV : 'development'
};