Skip to content

Instantly share code, notes, and snippets.

@helloamitpal
Created September 4, 2019 06:13
Show Gist options
  • Save helloamitpal/66ff17a7914312be9618ee682fd2107e to your computer and use it in GitHub Desktop.
Save helloamitpal/66ff17a7914312be9618ee682fd2107e to your computer and use it in GitHub Desktop.
PWA setup
{
"name": "WordPedia",
"version": "1.0.0",
"engines": {
"node": ">=8.10.0",
"npm": ">=5"
},
"description": "This is a learning app to improve the vocabulary of any language.",
"repository": {
"type": "git",
"url": "https://github.com/amit040386/WordPedia"
},
"license": "MIT",
"author": "Amit Pal",
"scripts": {
"prebuild": "npm run build:clean",
"build": "cross-env NODE_ENV=production webpack --config config/webpack.prod.babel.js --color -p --progress --hide-modules --display-optimization-bailout",
"build:clean": "rimraf ./build",
"clean": "npm run build:clean",
"eslint:fix": "eslint -- . --ignore-path .gitignore --fix",
"lint": "npm run lint:js",
"lint:eslint": "eslint --ignore-path .gitignore",
"lint:js": "npm run lint:eslint -- . ",
"start": "cross-env NODE_ENV=development nodemon server",
"start:prod": "cross-env NODE_ENV=production node server",
"start:production": "npm run build && npm run start:prod",
"pretest": "npm run lint"
},
"dependencies": {
"@babel/polyfill": "^7.0.0",
"agenda": "^2.0.2",
"axios": "^0.19.0",
"body-parser": "^1.19.0",
"chalk": "^2.3.2",
"compression": "^1.7.3",
"cors": "^2.8.5",
"dotenv": "^8.0.0",
"express": "4.16.3",
"helmet": "^3.19.0",
"ip": "1.1.5",
"lodash": "^4.17.11",
"minimist": "1.2.0",
"mongoose": "^5.6.7",
"node-schedule": "^1.3.2",
"prop-types": "^15.6.2",
"react": "^16.8.2",
"react-dom": "^16.8.2",
"react-ga": "^2.6.0",
"react-helmet": "^5.2.0",
"react-loadable": "^5.5.0",
"react-redux": "5.0.7",
"react-router-dom": "^4.3.1",
"react-select": "^3.0.4",
"react-toastify": "^5.3.2",
"redux": "3.7.2",
"redux-pack": "^0.1.5",
"redux-persist": "5.10.0",
"redux-thunk": "^2.3.0",
"sanitize.css": "^11.0.0",
"web-push": "^3.3.5"
},
"devDependencies": {
"@babel/cli": "7.1.2",
"@babel/core": "7.1.2",
"@babel/plugin-proposal-class-properties": "7.1.0",
"@babel/plugin-syntax-dynamic-import": "7.0.0",
"@babel/plugin-transform-modules-commonjs": "7.1.0",
"@babel/plugin-transform-react-constant-elements": "7.0.0",
"@babel/plugin-transform-react-inline-elements": "7.0.0",
"@babel/preset-env": "7.1.0",
"@babel/preset-react": "7.0.0",
"@babel/register": "^7.0.0",
"add-asset-html-webpack-plugin": "3.0.1",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "10.0.1",
"babel-loader": "8.0.4",
"babel-plugin-dynamic-import-node": "2.2.0",
"babel-plugin-lodash": "3.3.4",
"babel-plugin-react-transform": "3.0.0",
"babel-plugin-transform-react-remove-prop-types": "0.4.19",
"brotli-webpack-plugin": "^1.1.0",
"circular-dependency-plugin": "5.0.2",
"copy-webpack-plugin": "^5.0.4",
"cross-env": "5.2.0",
"css-loader": "1.0.0",
"eslint": "5.7.0",
"eslint-config-airbnb": "17.1.0",
"eslint-config-airbnb-base": "13.1.0",
"eslint-import-resolver-webpack": "0.10.1",
"eslint-plugin-import": "2.14.0",
"eslint-plugin-jsx-a11y": "6.1.2",
"eslint-plugin-react": "7.11.1",
"eventsource-polyfill": "0.9.6",
"exports-loader": "0.7.0",
"file-loader": "1.1.11",
"html-loader": "0.5.5",
"html-webpack-plugin": "3.2.0",
"imports-loader": "0.8.0",
"lint-staged": "7.3.0",
"node-plop": "0.16.0",
"node-sass": "^4.9.0",
"nodemon": "^1.19.1",
"null-loader": "0.1.1",
"plop": "2.1.0",
"postcss-flexbugs-fixes": "^4.1.0",
"postcss-loader": "^3.0.0",
"react-test-renderer": "^16.5.2",
"rimraf": "2.6.2",
"sass-loader": "^7.0.1",
"shelljs": "^0.8.1",
"style-loader": "0.23.1",
"url-loader": "1.1.2",
"webpack": "4.20.2",
"webpack-cli": "^3.1.2",
"webpack-dev-middleware": "3.4.0",
"webpack-hot-middleware": "2.24.3",
"webpack-pwa-manifest": "^4.0.0",
"whatwg-fetch": "^3.0.0",
"workbox-webpack-plugin": "^4.3.1"
},
"resolutions": {
"babel-core": "7.0.0-bridge.0"
},
"lint-staged": {
"linters": {
"src/**/*.js": "eslint",
"src/**/*.scss": "stylelint --syntax=scss"
}
}
}
/**
* COMMON WEBPACK CONFIGURATION
*/
const path = require('path');
const webpack = require('webpack');
const WebpackPwaManifest = require('webpack-pwa-manifest');
const BrotliPlugin = require('brotli-webpack-plugin');
const workboxPlugin = require('workbox-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
process.noDeprecation = true;
module.exports = (options) => ({
mode: options.mode,
entry: options.entry,
output: Object.assign(
{
// Compile into js/build.js
path: path.resolve(process.cwd(), 'build'),
publicPath: '/'
},
options.output
), // Merge with env dependent settings
module: {
rules: [
{
test: /\.js$/, // Transform all .js files required somewhere with Babel
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: options.babelQuery
}
},
{
// Preprocess our own .scss files
test: /\.scss$/,
exclude: /node_modules/,
use: ['style-loader', 'css-loader', 'sass-loader']
},
{
// Preprocess 3rd party .css files located in node_modules
test: /\.css$/,
include: /node_modules/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(eot|svg|otf|ttf|woff|woff2)$/,
use: 'file-loader'
},
{
test: /\.(jpg|png|gif)$/,
use: 'file-loader'
},
{
test: /\.html$/,
use: 'html-loader'
},
{
test: /\.(mp4|webm)$/,
use: {
loader: 'url-loader',
options: {
limit: 10000
}
}
}
]
},
plugins: options.plugins.concat([
new webpack.ProvidePlugin({
// make fetch available
fetch: 'exports-loader?self.fetch!whatwg-fetch'
}),
// Always expose NODE_ENV to webpack, in order to use `process.env.NODE_ENV`
// inside your code for any environment checks; UglifyJS will automatically
// drop any unreachable code.
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV)
}
}),
new BrotliPlugin({
asset: '[path].br[query]',
test: /\.(js|css|html|svg)$/,
threshold: 10240,
minRatio: 0.8
}),
// copying service worker custom files for listening push notifications
new CopyWebpackPlugin([
{ from: 'push-notifications.js', to: 'push-notifications.js', context: 'app/' }
]),
// service Worker settings
new workboxPlugin.GenerateSW({
swDest: 'service-worker.js',
clientsClaim: true,
cacheId: 'WordPedia',
offlineGoogleAnalytics: true,
cleanupOutdatedCaches: true,
importScripts: ['push-notifications.js'],
skipWaiting: true,
runtimeCaching: [{
urlPattern: /\.svg$/,
handler: 'CacheFirst'
}, {
urlPattern: /.*/,
handler: 'NetworkFirst'
}, {
urlPattern: /api/,
handler: 'NetworkFirst',
options: {
networkTimeoutSeconds: 10,
cacheName: 'WordPedia-api-cache',
expiration: {
maxEntries: 5,
maxAgeSeconds: 60
},
cacheableResponse: {
statuses: [0, 200]
}
}
}]
}),
// PWA settings
new WebpackPwaManifest({
name: 'WordPedia',
short_name: 'WordPedia',
description: 'This is a learning app to improve the vocabulary.',
background_color: '#ffffff',
theme_color: '#ffffff',
start_url: '/',
display: 'standalone',
orientation: 'portrait',
author: {
name: 'Amit Pal',
website: 'https://www.linkedin.com/in/amit-pal-0241423a/',
github: 'https://github.com/amit040386/WordPedia'
},
icons: [
{
src: path.resolve('app/images/logos/WordPedia-512x512.png'),
sizes: [96, 192, 512]
}
]
})
]),
resolve: {
modules: ['app', 'node_modules'],
extensions: ['.js', '.jsx', '.scss', '.react.js'],
mainFields: ['browser', 'jsnext:main', 'main']
},
devtool: options.devtool,
target: 'web', // Make web variables accessible to webpack, e.g. window
performance: options.performance || {},
optimization: {
namedModules: true,
splitChunks: {
name: 'vendor',
minChunks: 2
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment