initial setup

This commit is contained in:
Jeff Colombo 2019-01-02 18:25:58 -05:00
parent dbfe019e26
commit 4bb729e962
15 changed files with 5946 additions and 0 deletions

14
.babelrc Normal file
View File

@ -0,0 +1,14 @@
{
"presets": [
"es2015",
"react"
],
"plugins": [
"transform-flow-strip-types",
"transform-class-properties",
"transform-object-rest-spread",
["transform-builtin-extend", {
"globals": ["Error", "Array"]
}]
]
}

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
node_modules
dist
yarn-error.log

9
.stylelintrc Normal file
View File

@ -0,0 +1,9 @@
{
"extends": "stylelint-config-standard",
"rules": {
"selector-pseudo-class-no-unknown": true,
"selector-pseudo-element-no-unknown": true,
"selector-type-no-unknown": true,
"media-feature-name-no-unknown": true
}
}

94
cssConcatenator.js Normal file
View File

@ -0,0 +1,94 @@
// inspired by https://github.com/lydell/source-map-concat
var fs = require('fs');
var path = require('path');
var concat = require('source-map-concat');
var glob = require('glob');
var resolveSourceMapSync = require('source-map-resolve').resolveSourceMapSync;
var createDummySourceMap = require('source-map-dummy');
// console.log(process.argv);
var sourceWorkingDirectory = null;
var sourceFiles = null;
var output = null;
var sourceMaps = false;
if (process.argv.length < 4 || process.argv.length > 6) {
throw new Error('invalid arguments');
}
process.argv.forEach(function (argument, index) {
if (index > 1) {
if (index === 2) {
sourceWorkingDirectory = argument;
} else if (index === 3) {
sourceFiles = sourceWorkingDirectory + '/' + argument;
} else if (index === 4) {
output = sourceWorkingDirectory + '/' + argument;
} else if (index === 5) {
sourceMaps = argument == 'true'; // intentionally loose ==
}
}
});
// console.log(sourceWorkingDirectory, sourceFiles, output, sourceMaps);
glob(sourceFiles, {
nodir: true,
nosort: true
}, function (error, files) {
// console.log(error, files);
// files is an array of filenames.
// If the `nonull` option is set, and nothing
// was found, then files is ["**/*.js"]
// er is an error object or null.
if (error) {
throw error;
}
sourceFiles = files.map(function(file) {
return {
source: file,
code: '/** Source: ' + file + ' */\n' + fs.readFileSync(file).toString()
}
});
if (sourceMaps) {
sourceFiles.forEach(function (file) {
var previousMap = resolveSourceMapSync(file.code, file.source, fs.readFileSync);
if (previousMap) {
file.map = previousMap.map;
file.sourcesRelativeTo = previousMap.sourcesRelativeTo;
} else {
file.map = createDummySourceMap(file.code, {
source: file.source,
type: 'css'
});
}
});
}
var concatenated = concat(sourceFiles, {
delimiter: '\n',
mapPath: sourceMaps ? output + '.map' : null
});
var outputFile = path.basename(output);
concatenated.prepend('/* Generated by cssConcatenator.js */\n');
if (sourceMaps) {
concatenated.add('\n/*# sourceMappingURL=' + outputFile + '.map*/');
}
var result = concatenated.toStringWithSourceMap({
file: outputFile
});
fs.writeFileSync(output, result.code);
if (sourceMaps) {
fs.writeFileSync(output + '.map', result.map.toString());
}
});

3
generatePokemonData.ts Normal file
View File

@ -0,0 +1,3 @@
const gameMaster = require('pokemongo-game-master');
gameMaster.getVersion('latest', 'json').then(console.log);

45
package.json Normal file
View File

@ -0,0 +1,45 @@
{
"scripts": {
"#": "DO NOT ADD '-d' OPTION TO WEBPACK OR ALL SOURCEMAPS WILL BREAK: https://webpack.js.org/api/cli/#shortcuts",
"package": "yarn webpack -- --config webpack.config.prod.js --bail --display-used-exports -p",
"package-for-test": "yarn webpack -- --config webpack.config.test.js --bail --display-used-exports",
"watch": "yarn webpack -- --config webpack.config.js --colors --debug --output-pathinfo --progress --watch",
"webpack": "node ./node_modules/webpack/bin/webpack.js --cache=true --display-error-details --profile"
},
"devDependencies": {
"@types/react": "^16.7.18",
"@types/react-dom": "^16.0.11",
"babel-loader": "^8.0.4",
"babel-polyfill": "^6.26.0",
"css-loader": "^2.1.0",
"fs": "^0.0.1-security",
"glob": "^7.1.3",
"mini-css-extract-plugin": "^0.5.0",
"node-sass": "^4.11.0",
"path": "^0.12.7",
"pokemongo-game-master": "^1.0.4",
"sass-loader": "^7.1.0",
"source-map-concat": "^1.0.1",
"source-map-dummy": "^1.0.0",
"source-map-loader": "^0.2.4",
"source-map-resolve": "^0.5.2",
"style-loader": "^0.23.1",
"stylelint": "^9.9.0",
"stylelint-config-standard": "^18.2.0",
"stylelint-webpack-plugin": "^0.10.5",
"ts-loader": "^5.3.2",
"tslint": "^5.12.0",
"tslint-eslint-rules": "^5.4.0",
"tslint-loader": "^3.5.4",
"tslint-misc-rules": "^3.5.1",
"tslint-react": "^3.6.0",
"typescript": "^3.2.2",
"webpack": "^4.28.3",
"webpack-cli": "^3.1.2",
"webpack-shell-plugin": "^0.5.0"
},
"dependencies": {
"react": "^16.7.0",
"react-dom": "^16.7.0"
}
}

3
src/scss/index.scss Normal file
View File

@ -0,0 +1,3 @@
body {
background: red;
}

9
src/ts/index.tsx Normal file
View File

@ -0,0 +1,9 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import 'styles/index.scss';
ReactDOM.render(
<h1>Hello Mons</h1>,
document.body
);

26
tsconfig.json Normal file
View File

@ -0,0 +1,26 @@
{
"compileOnSave": true,
"compilerOptions": {
"strict": true,
"noUnusedLocals": false,
"allowJs": true,
"outDir": "./dist",
"sourceMap": true,
"module": "commonjs",
"target": "es6",
"jsx": "react",
"baseUrl": ".",
"traceResolution": false,
"paths": {},
"plugins": [{
"name": "tslint-language-service",
"disableNoUnusedVariableRule": false
}]
},
"include": [
"./src"
],
"exclude": [
"node_modules",
]
}

53
tslint.json Normal file
View File

@ -0,0 +1,53 @@
{
"extends": ["tslint:latest", "tslint-react", "tslint-eslint-rules"],
"rules": {
"no-default-export": true,
"no-unused-expression": true,
"no-unused-variable": [true, "react"],
"no-submodule-imports": false,
"space-before-function-paren": [true, {"anonymous": "always"}],
"trailing-comma": false,
"max-line-length": [true, 240],
"no-namespace": false,
"no-empty-interface": false,
"jsx-curly-spacing": [true, "always"],
"jsx-no-multiline-js": false,
"quotemark": [true, "single", "jsx-double"],
"object-literal-key-quotes": [true, "as-needed"],
"object-literal-sort-keys" : false,
"array-type": [true, "generic"],
"prefer-for-of": false,
"typedef-whitespace": [
true, {
"call-signature": "onespace",
"index-signature": "onespace",
"parameter": "onespace",
"property-declaration": "onespace",
"variable-declaration": "onespace"
}, {
"call-signature": "onespace",
"index-signature": "onespace",
"parameter": "onespace",
"property-declaration": "onespace",
"variable-declaration": "onespace"
}
],
"prefer-conditional-expression": false,
"jsx-attribute-spacing": true,
"jsx-expression-spacing": true,
"jsx-no-braces-for-string-attributes": true,
"no-braces-for-single-line-arrow-functions": true,
"object-curly-spacing": [true, "always"]
},
"defaultSeverity": "warning",
"rulesDirectory": [
"./node_modules/tslint-misc-rules/rules"
],
"linterOptions": {
"exclude": [
"./src/**/*.spec.*"
]
}
}

148
webpack.config.js Normal file
View File

@ -0,0 +1,148 @@
const path = require('path');
const options = require('./webpack.config.options');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const typescriptResolve = {
alias: {
'moment$': path.resolve('./node_modules/moment/min/moment-with-locales.min.js'),
'moment-timezone$': path.resolve('./node_modules/moment-timezone/builds/moment-timezone-with-data-2012-2022.min.js'),
'styles': path.resolve('./src/scss'),
},
extensions: ['.ts', '.tsx', '.js'],
};
module.exports = function (env, tsLoaderHappyPackMode) {
env = env || {};
tsLoaderHappyPackMode = (typeof tsLoaderHappyPackMode === 'undefined') ? true : tsLoaderHappyPackMode;
console.log('Webpack Environment:', env, 'tsLoaderHappyPackMode:', !!tsLoaderHappyPackMode);
const plugins = [
new StyleLintPlugin({
configFile: '.stylelintrc',
context: 'src',
emitErrors: true,
failOnError: false,
quiet: false,
}),
].concat(options.getPlugins(env));
return {
entry: {
'dist/global': [
'babel-polyfill', // this is intended to be on every single page, legacy or new!
'./src/scss/index.scss' // these are the global styles that should never be imported by a component
],
'dist/main': './src/ts/index.tsx',
},
optimization: options.getOptimizations(),
output: {
path: path.resolve(options.outputDirectory),
filename: '[name]-bundle.js',
// filename: '[name]-bundle.[chunkhash].js',
sourceMapFilename: '[file].map'
},
resolve: typescriptResolve,
devtool: 'source-map',
plugins: plugins,
module: {
rules: [
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{
test: /\.js$/,
enforce: 'pre',
exclude: /node_modules/,
use: [
{ loader: 'source-map-loader' }
]
},
{
test: /\.tsx?$/,
enforce: 'pre',
exclude: /node_modules/,
use: [
{ loader: 'source-map-loader' },
]
},
{
test: /\.tsx?$/,
enforce: 'pre',
exclude: /node_modules/,
use: [
{
loader: 'tslint-loader',
options: {
emitErrors: !env.WARN_ON_LINT,
failOnHint: !env.WARN_ON_LINT,
typeCheck: false,
}
},
]
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
{ loader: 'babel-loader' }
]
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: [
{ loader: 'babel-loader' },
{
loader: 'ts-loader',
options: {
silent: true,
happyPackMode: tsLoaderHappyPackMode, // setting as true also implies transpileOnly: true,
}
}
]
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
// you can specify a publicPath here
// by default it use publicPath in webpackOptions.output
// publicPath: '../'
}
},
{
loader: 'css-loader',
options: {
sourceMap: !!env.CSS_SOURCEMAPS
}
},
{
loader: 'sass-loader',
options: {
sourceMap: !!env.CSS_SOURCEMAPS
}
}
]
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
sourceMap: !!env.CSS_SOURCEMAPS
}
}
],
}
]
}
}
};

69
webpack.config.options.js Normal file
View File

@ -0,0 +1,69 @@
const webpack = require('webpack');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const WebpackShellPlugin = require('webpack-shell-plugin');
const outputDirectory = './dist';
module.exports.outputDirectory = outputDirectory;
module.exports.getOptimizations = function () {
return {
splitChunks: {
cacheGroups: {
commons: {
name: 'commons',
filename: 'js/commons-bundle.js',
chunks: 'initial',
// (the filename of the commons chunk)
minChunks: 2,
}
}
}
};
// new webpack.optimize.CommonsChunkPlugin({
// name: 'vendor',
// filename: 'vendor-bundle.js',
// minChunks: function (module) {
// return (module.context || '').indexOf('node_modules') !== -1;
// }
// }),
// new webpack.optimize.CommonsChunkPlugin({
// // (the commons chunk name)
// name: 'commons',
// // (the filename of the commons chunk)
// filename: 'js/commons-bundle.js',
// minChunks: function(module, count) {
// // (Modules must be shared between 2 entries or be included by the globally-exposed-dependencies-bundle)
// return /*(module.context || '').indexOf('node_modules') === -1 && */count >= 2;
// },
// }),
};
module.exports.getPlugins = function (env) {
env = env || {};
return [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment\/min$/),
new webpack.optimize.ModuleConcatenationPlugin(), // --display-optimization-bailout
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: '[name].css',
// filename: (getPath) => {
// // output the css into the css directory instead of the js directory (where the bundles are)
// return 'css/' + getPath('[name].tmp.css').replace(/^js\//, '');
// },
// chunkFilename: "[id].css"
}),
new WebpackShellPlugin({
dev: false,
onBuildEnd:[
'echo "Starting CSS Merging"',
'node cssConcatenator.js ' + outputDirectory + '/css global.tmp.css global.css ' + !!env.CSS_SOURCEMAPS,
'node cssConcatenator.js ' + outputDirectory + '/css !(global).tmp.css app.css ' + !!env.CSS_SOURCEMAPS,
'node cssConcatenator.js ' + outputDirectory + '/css {commons,public/public-site}.tmp.css public/public.css ' + !!env.CSS_SOURCEMAPS,
'node cssConcatenator.js ' + outputDirectory + '/css {global,commons,public/drink-price-tool}.tmp.css public/drink-price-tool.css ' + !!env.CSS_SOURCEMAPS,
'node cssConcatenator.js ' + outputDirectory + '/css {global,public/bar-profit-tool}.tmp.css public/bar-profit-tool.css ' + !!env.CSS_SOURCEMAPS,
'node cssConcatenator.js ' + outputDirectory + '/css public/start-free-trial.tmp.css public/start-free-trial.css ' + !!env.CSS_SOURCEMAPS
]
})
];
};

44
webpack.config.prod.js Normal file
View File

@ -0,0 +1,44 @@
const webpack = require('webpack');
const config = require('./webpack.config');
const options = require('./webpack.config.options');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const StyleLintPlugin = require('stylelint-webpack-plugin');
module.exports = function(env) {
var generatedConfig = config(env, false);
generatedConfig.plugins = [
new webpack.LoaderOptionsPlugin({
minimize: true
}),
new StyleLintPlugin({
configFile: '.stylelintrc',
context: 'src',
emitErrors: true,
failOnError: true,
quiet: false,
}),
// Lesman 10/03/2017
// This plugin enforces case sensitive paths in order
// to give build consistency across systems (OsX is not case sensitive)
// however the plugin is relatively slow (adds ~20 seconds to the build)
// and our jenkins system is already case-sensitive so it's not critical
// The plugin does provide better error message though, so we may want to
// re-enable it if case-sensitivity build problems are an issue
// new CaseSensitivePathsPlugin({debug: true}),
new webpack.optimize.UglifyJsPlugin({
// compress: {
// warnings: true
// },
sourceMap: true
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV' : JSON.stringify('production')
}),
].concat(options.getPlugins(env || {}));
return generatedConfig;
}

42
webpack.config.test.js Normal file
View File

@ -0,0 +1,42 @@
const config = require('./webpack.config');
const options = require('./webpack.config.options');
const StyleLintPlugin = require('stylelint-webpack-plugin');
module.exports = function(env) {
const generatedConfig = config(env, false);
delete generatedConfig.devtool;
generatedConfig.plugins = [
new StyleLintPlugin({
configFile: '.stylelintrc',
context: 'src',
emitErrors: true,
failOnError: true,
quiet: false,
}),
].concat(options.getPlugins(env || {}));
return generatedConfig;
// Lesman 9/29/2017
// I thought this might make stuff faster?
// but it doesn't seem to
// var rules = generatedConfig.module.rules;
// for (var i = 0; i < rules.length; i++) {
// var use = rules[i].use;
// for (var j = 0; j < use.length; j++) {
// var loader = use[j];
// if (loader === 'source-map-loader') {
// use.splice(j);
// j--;
// continue;
// }
// if (loader.options !== undefined) {
// if (loader.options.sourceMap !== undefined) {
// loader.options.sourcemap = false;
// }
// }
// }
// }
}

5384
yarn.lock Normal file

File diff suppressed because it is too large Load Diff