build(webpack): parcel to webpack (#14410)

* build(ts): add ts webpack dependencies and config

* wip(webpack.dev): css and js compiling

* wip(webpack): building assets with watch

* fix(webpack): fix page reloads not serving assets

* build(webpack): fork typechecking

* chore(webpack): rename dev config

* build(webpack): add production config

* build(webpack): add process vendor in separate build

* build(webpack): change dev source map

* build(webpack): dont lint in prod builds

* build(webpack): move reduce redundancy for GIT_SHA

* docs(ui): update README

* build(webpack): add hash to production build
pull/14431/head
Andrew Watkins 2019-07-23 14:10:34 -07:00 committed by GitHub
parent 48ee7ada04
commit d2933cc184
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 2464 additions and 134 deletions

View File

@ -1,6 +1,7 @@
## Packages
### Adding new packages
To add a new package, run
```sh
@ -14,6 +15,7 @@ yarn add packageName --dev
```
### Updating a package
First, run
```sh
@ -32,4 +34,9 @@ yarn upgrade packageName
```
## Testing
Tests can be run via command line with `yarn test`, from within the `/ui` directory. For more detailed reporting, use `yarn test -- --reporters=verbose`.
## Starting Dev Server
The assets are built by running `yarn start` from withing the `/ui` directory. The dev server with hot reloading runs at `localhost:8080`.

11
ui/assets/index.html Normal file
View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>InfluxDB 2.0</title>
<base href="/" />
</head>
<body>
<div id="react-root" data-basepath=""></div>
</body>
</html>

View File

@ -93,7 +93,11 @@ describe('tokens', () => {
cy.getByTestID('table-row').then(rows => {
authData = authData.sort((a, b) =>
// eslint-disable-next-line
a.description < b.description ? -1 : a.description > b.description ? 1 : 0
a.description < b.description
? -1
: a.description > b.description
? 1
: 0
)
for (var i = 0; i < rows.length; i++) {
@ -257,7 +261,6 @@ describe('tokens', () => {
})
cy.getByTestID('button--save').click()
cy.getByTestID('overlay--container').should('not.be.visible')
//Verify token
cy.getByTestID('table-row')

View File

@ -16,8 +16,9 @@
"src": "./src"
},
"scripts": {
"start": "yarn install && GIT_SHA=$(git rev-parse HEAD) parcel watch --no-autoinstall -d build src/index.html",
"build": "yarn install --silent && GIT_SHA=$(git rev-parse HEAD) parcel build -d build --log-level 2 src/index.html",
"start": "yarn install && cross-env TS_NODE_PROJECT=\"webpack.tsconfig.json\" && yarn run build:vendor && webpack-dev-server --config ./webpack.dev.ts",
"build": "yarn install --silent && webpack --config webpack.prod.ts",
"build:vendor": "webpack --config webpack.vendor.ts",
"clean": "rm -rf ./build && rm -rf ./.cache && rm -rf node_modules && rm -rf cypress/screenshots && rm -rf cypress/videos && rm -f junit-results/* ",
"test": "jest --maxWorkers=2",
"test:watch": "jest --watch --verbose false",
@ -31,7 +32,6 @@
"eslint": "eslint '{src,cypress}/**/*.{ts,tsx}'",
"eslint:fix": "eslint --fix '{src,cypress}/**/*.{ts,tsx}'",
"tsc": "tsc -p ./tsconfig.json --noEmit --pretty --skipLibCheck",
"tsc:watch": "tsc -p ./tsconfig.json --noEmit --pretty -w",
"tsc:cypress": "tsc -p ./cypress/tsconfig.json --noEmit --pretty --skipLibCheck",
"cy": "cypress open"
},
@ -77,8 +77,8 @@
},
"author": "",
"devDependencies": {
"@babel/core": "^7.2.2",
"@babel/preset-env": "^7.3.1",
"@babel/core": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@cypress/webpack-preprocessor": "^4.0.3",
"@types/chroma-js": "^1.3.4",
"@types/codemirror": "^0.0.56",
@ -91,11 +91,12 @@
"@types/levelup": "^3.1.0",
"@types/lodash": "^4.14.116",
"@types/memoize-one": "^4.0.2",
"@types/node": "^9.4.6",
"@types/node": "^12.6.8",
"@types/papaparse": "^4.5.9",
"@types/prop-types": "^15.5.2",
"@types/qs": "^6.5.1",
"@types/react": "^16.8.3",
"@types/react-datepicker": "^2.8.1",
"@types/react-dnd": "^2.0.36",
"@types/react-dnd-html5-backend": "^2.1.9",
"@types/react-dom": "^16.8.1",
@ -106,12 +107,16 @@
"@types/react-virtualized": "^9.18.3",
"@types/text-encoding": "^0.0.32",
"@types/uuid": "^3.4.3",
"@types/webpack": "^4.4.35",
"@typescript-eslint/eslint-plugin": "^1.4.0",
"@typescript-eslint/parser": "^1.4.0",
"acorn": "^6.0.6",
"ajv": "^6.7.0",
"autoprefixer": "^6.3.1",
"babel-loader": "^8.0.5",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"cross-env": "^5.2.0",
"css-loader": "^3.1.0",
"cypress": "^3.2.0",
"enzyme": "^3.6.0",
"enzyme-adapter-react-16": "^1.6.0",
@ -121,22 +126,33 @@
"eslint-plugin-prettier": "^3.0.1",
"eslint-plugin-react": "^7.12.4",
"express": "^4.14.0",
"file-loader": "^4.1.0",
"fork-ts-checker-webpack-plugin": "^1.4.3",
"html-webpack-plugin": "^3.2.0",
"http-proxy-middleware": "^0.18.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^24.8.0",
"jsdom": "^9.0.0",
"junit-viewer": "^4.11.1",
"mini-css-extract-plugin": "^0.8.0",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.18.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"parcel": "^1.12.3",
"prettier": "^1.16.4",
"react-testing-library": "^5.4.4",
"sass": "^1.15.3",
"sass": "^1.22.7",
"sass-loader": "^7.1.0",
"terser-webpack-plugin": "^1.3.0",
"ts-jest": "^24.0.0",
"ts-loader": "^5.3.3",
"tslib": "^1.9.0",
"typescript": "^3.3.3",
"webpack": "^4.29.0"
"webpack": "^4.29.0",
"webpack-cli": "^3.3.6",
"webpack-dev-server": "^3.7.2",
"webpack-merge": "^4.2.1",
"ts-node": "^8.3.0"
},
"dependencies": {
"@influxdata/clockface": "0.0.13",
@ -187,7 +203,6 @@
"redux-thunk": "^1.0.3",
"reselect": "^4.0.0",
"rome": "^2.1.22",
"ui": "^0.2.4",
"uuid": "^3.2.1"
}
}

View File

@ -37,15 +37,15 @@ class TokenRow extends PureComponent<Props> {
<IndexList.Row>
<IndexList.Cell>
<EditableName
onUpdate={this.handleUpdateName}
name={description}
onUpdate={this.handleUpdateName}
noNameString={DEFAULT_TOKEN_DESCRIPTION}
onEditName={this.handleClickDescription}
/>
</IndexList.Cell>
<IndexList.Cell>
<SlideToggle
active={this.isTokenEnbled}
active={this.isTokenEnabled}
size={ComponentSize.ExtraSmall}
onChange={this.changeToggle}
/>
@ -62,7 +62,7 @@ class TokenRow extends PureComponent<Props> {
)
}
private get isTokenEnbled(): boolean {
private get isTokenEnabled(): boolean {
const {auth} = this.props
return auth.status === AuthorizationUpdateRequest.StatusEnum.Active
}

View File

@ -33,7 +33,7 @@ interface State {
@ErrorHandling
class EditableName extends Component<Props, State> {
public static defaultProps = {
hrefValue: '#',
hrefValue: 'javascript:void(0);',
testID: 'editable-name',
}

View File

@ -76,7 +76,7 @@ export default class DatePicker extends PureComponent<Props, State> {
</Form.Element>
<div className="range-picker--popper-container">
<ReactDatePicker
inline
inline={true}
selected={date}
onChange={this.handleSelectDate}
startOpen={true}

View File

@ -14,21 +14,21 @@
@import 'src/clockface/styles';
// Components
@import 'src/shared/components/ColorDropdown';
@import 'src/shared/components/avatar/Avatar';
@import 'src/shared/components/tables/TableGraphs';
@import 'src/shared/components/notifications/Notifications';
@import 'src/shared/components/threesizer/Threesizer';
@import 'src/shared/components/graph_tips/GraphTips';
@import 'src/shared/components/cells/Dashboards';
@import 'src/shared/components/splash_page/SplashPage';
@import 'src/shared/components/code_mirror/CodeMirror';
@import 'src/shared/components/code_mirror/CodeMirrorTheme';
@import 'src/dashboards/components/dashboard_empty/DashboardEmpty';
@import 'src/shared/components/views/Markdown';
@import 'src/shared/components/custom_singular_time/CustomSingularTime';
@import 'src/shared/components/ColorDropdown.scss';
@import 'src/shared/components/avatar/Avatar.scss';
@import 'src/shared/components/tables/TableGraphs.scss';
@import 'src/shared/components/notifications/Notifications.scss';
@import 'src/shared/components/threesizer/Threesizer.scss';
@import 'src/shared/components/graph_tips/GraphTips.scss';
@import 'src/shared/components/cells/Dashboards.scss';
@import 'src/shared/components/splash_page/SplashPage.scss';
@import 'src/shared/components/code_mirror/CodeMirror.scss';
@import 'src/shared/components/code_mirror/CodeMirrorTheme.scss';
@import 'src/dashboards/components/dashboard_empty/DashboardEmpty.scss';
@import 'src/shared/components/views/Markdown.scss';
@import 'src/shared/components/custom_singular_time/CustomSingularTime.scss';
@import 'src/onboarding/OnboardingWizard.scss';
@import 'src/shared/components/columns_options/ColumnsOptions';
@import 'src/shared/components/columns_options/ColumnsOptions.scss';
@import 'src/shared/components/InputClickToEdit.scss';
@import 'src/shared/components/ImportOverlay.scss';
@import 'src/shared/components/VersionInfo.scss';

View File

@ -26,5 +26,11 @@
"esModuleInterop": true,
"baseUrl": "./"
},
"exclude": ["assets", "build", "node_modules", "cypress"]
"exclude": [
"assets",
"build",
"node_modules",
"cypress",
"webpack.tsconfig.json"
]
}

94
ui/webpack.common.ts Normal file
View File

@ -0,0 +1,94 @@
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
const webpack = require('webpack')
const GIT_SHA = require('child_process')
.execSync('git rev-parse HEAD')
.toString()
const devMode = process.env.NODE_ENV !== 'production'
module.exports = {
context: __dirname,
output: {
filename: devMode ? '[name].bundle.js' : '[name].[hash].bundle.js',
path: path.resolve(__dirname, 'build'),
},
entry: {
app: './src/index.tsx',
},
resolve: {
alias: {
src: path.resolve(__dirname, 'src'),
},
extensions: ['.tsx', '.ts', '.js'],
},
module: {
rules: [
{
test: /\.tsx?$/,
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true,
},
},
],
},
{
test: /\.s?css$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'sass-loader',
options: {
implementation: require('sass'),
hmr: process.env.NODE_ENV === 'development',
},
},
],
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ['file-loader'],
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: ['file-loader'],
},
],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
filename: 'index.html',
template: './assets/index.html',
favicon: './assets/images/favicon.ico',
inject: 'body',
}),
new MiniCssExtractPlugin({
filename: devMode ? '[name].css' : '[name].[hash].css',
chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
}),
new ForkTsCheckerWebpackPlugin({
eslint: !devMode,
warningsFilter: /export * was not found in/,
}),
new webpack.ProgressPlugin(),
new webpack.EnvironmentPlugin({...process.env, GIT_SHA}),
],
stats: {
colors: true,
children: false,
modules: false,
version: false,
assetsSort: '!size',
warningsFilter: /export .* was not found in/,
excludeAssets: [/\.(hot-update|woff|eot|ttf|svg|ico|png)/],
},
performance: {hints: false},
}

24
ui/webpack.dev.ts Normal file
View File

@ -0,0 +1,24 @@
export {}
const merge = require('webpack-merge')
const webpack = require('webpack')
const common = require('./webpack.common.ts')
const path = require('path')
module.exports = merge(common, {
mode: 'development',
devtool: 'cheap-inline-source-map',
devServer: {
hot: true,
historyApiFallback: true,
compress: true,
proxy: {
'/api/v2': 'http://localhost:9999',
},
},
plugins: [
new webpack.DllReferencePlugin({
context: path.join(__dirname, 'build'),
manifest: require('./build/vendor-manifest.json'),
}),
],
})

15
ui/webpack.prod.ts Normal file
View File

@ -0,0 +1,15 @@
const merge = require('webpack-merge')
const common = require('./webpack.common.ts')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const TerserJSPlugin = require('terser-webpack-plugin')
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map',
optimization: {
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
splitChunks: {
chunks: 'all',
},
},
})

14
ui/webpack.tsconfig.json Normal file
View File

@ -0,0 +1,14 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"esModuleInterop": true
},
"exclude": [
"assets",
"build",
"node_modules",
"cypress",
"webpack.tsconfig.json"
]
}

36
ui/webpack.vendor.ts Normal file
View File

@ -0,0 +1,36 @@
export {}
const webpack = require('webpack')
const path = require('path')
const {dependencies} = require('./package.json')
// only dll infrequently updated dependencies
const vendor = Object.keys(dependencies).filter(d => !d.includes('@influxdata'))
module.exports = {
context: __dirname,
mode: 'development',
entry: {
vendor,
},
output: {
path: path.join(__dirname, 'build'),
filename: '[name].bundle.js',
library: '[name]',
},
plugins: [
new webpack.DllPlugin({
name: '[name]',
path: path.join(__dirname, 'build', '[name]-manifest.json'),
}),
],
stats: {
colors: true,
children: false,
modules: false,
version: false,
assetsSort: '!size',
warningsFilter: /export .* was not found in/,
excludeAssets: [/\.(hot-update|woff|eot|ttf|svg|ico|png)/],
},
performance: {hints: false},
}

File diff suppressed because it is too large Load Diff