Skip to content

Commit

Permalink
Merge pull request #34 from ddhp/better-webpack
Browse files Browse the repository at this point in the history
Better webpack
  • Loading branch information
ddhp authored Nov 13, 2018
2 parents a0737c8 + 7e51b4c commit 82b1508
Show file tree
Hide file tree
Showing 11 changed files with 2,826 additions and 3,525 deletions.
40 changes: 27 additions & 13 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
{
"presets": ["react", "env", "stage-2"],
"presets": [
"@babel/react",
"@babel/preset-env"
],
"env": {
"test": {
"plugins": ["istanbul"]
"plugins": [
"istanbul"
]
}
},
"plugins": [
"transform-runtime",
"@babel/plugin-transform-runtime",
"@babel/plugin-proposal-class-properties",
["transform-imports", {
"lodash": {
"transform": "lodash/${member}",
"preventFullImport": true
}
}],
"react-hot-loader/babel",
["react-css-modules", {
"filetypes": {
// set this to activate scss support
".scss": {
"syntax": "postcss-scss",
[
"react-css-modules",
{
"filetypes": {
".scss": {
"syntax": "postcss-scss"
}
},
},
"webpackHotModuleReloading": true,
"generateScopedName": "[local]___[hash:base64:5]",
"handleMissingStyleName": "warn",
}]
"webpackHotModuleReloading": true,
"generateScopedName": "[local]___[hash:base64:5]",
"handleMissingStyleName": "warn"
}
]
]
}
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@ This boilerplate would help you build a react/redux/react-router isomorphic/univ
- production ready.
- webpack v4 support.
- manage your style in [CSS Modules](https://github.com/css-modules/css-modules) way.
- babel v7
- optimize bundle size by implementing [tree shaking](https://webpack.js.org/guides/tree-shaking/) (getting rid of moment.js is on the way [#35](https://github.com/ddhp/react-isomorphic-boilerplate/issues/35))

## Concept
### Getting Started
```
# we need babel-node to execute es6 server scripts
npm install -g babel-cli
# install dependencies
yarn
Expand Down
94 changes: 53 additions & 41 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,73 +3,81 @@
"version": "0.6.1",
"main": "src/server/index.js",
"license": "MIT",
"engines": {
"node": "^6.14.0 || ^8.10.0 || >=9.10.0"
},
"scripts": {
"start": "DEBUG=*,-nodemon*,-express*,-send,-babel*,-eslint*,-css-modules* NODE_ENV=hot babel-node --inspect src/server/hot/index.js",
"build:browser:dev": "webpack --env=dev --config=webpack.browser.babel.js --profile --progress --json > compilation-stats.json",
"start": "DEBUG=*,-nodemon*,-express*,-send,-babel*,-eslint*,-css-modules* NODE_ENV=hot npx babel-node --inspect src/server/hot/index.js",
"build:browser:dev": "node webpack-browser-runner dev",
"build:server:dev": "webpack --env=dev --config=webpack.server.babel.js --progress --profile --colors",
"build:browser:prod": "webpack --env=prod --config=webpack.browser.babel.js --progress --json > compilation-stats.json",
"build:browser:prod": "node webpack-browser-runner prod",
"build:server:prod": "webpack --env=prod --config=webpack.server.babel.js --progress --profile --colors",
"eslint": "eslint ./",
"test": "npm run eslint && cross-env NODE_ENV=test nyc ava --verbose",
"coverage": "nyc report --reporter=lcov",
"report": "cross-env NODE_ENV=test nyc ava && yarn run coverage"
},
"devDependencies": {
"@babel/cli": "^7.1.5",
"@babel/core": "^7.1.5",
"@babel/node": "^7.0.0",
"@babel/plugin-proposal-class-properties": "^7.1.0",
"@babel/plugin-transform-runtime": "^7.1.0",
"@babel/preset-env": "^7.1.5",
"@babel/preset-react": "^7.0.0",
"@babel/register": "^7.0.0",
"asset-require-hook": "^1.2.0",
"autoprefixer": "^9.0.1",
"ava": "^0.25.0",
"babel-core": "^6.26.0",
"babel-eslint": "^8.0.1",
"babel-loader": "^7.1.2",
"babel-plugin-istanbul": "^4.1.5",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.0",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"autoprefixer": "^9.3.1",
"ava": "^1.0.0-rc.2",
"babel-eslint": "^10.0.1",
"babel-loader": "^8.0.4",
"babel-plugin-istanbul": "^5.1.0",
"babel-plugin-transform-imports": "^1.5.1",
"codecov": "^3.0.0",
"cross-env": "^5.2.0",
"css-loader": "^1.0.0",
"css-modules-require-hook": "^4.2.3",
"enzyme": "^3.2.0",
"enzyme-adapter-react-16": "^1.1.0",
"eslint": "^4.19.1",
"eslint-config-airbnb": "^17.0.0",
"eslint": "^5.9.0",
"eslint-config-airbnb": "^17.1.0",
"eslint-loader": "^2.1.0",
"eslint-plugin-import": "^2.13.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.1",
"eslint-plugin-react": "^7.10.0",
"file-loader": "^1.1.5",
"eslint-plugin-react": "^7.11.1",
"file-loader": "^2.0.0",
"ignore-styles": "^5.0.1",
"mini-css-extract-plugin": "^0.4.1",
"mini-css-extract-plugin": "^0.4.4",
"mkdirp": "^0.5.1",
"mock-require": "^3.0.1",
"node-sass": "^4.9.2",
"nyc": "^12.0.2",
"node-sass": "^4.10.0",
"nyc": "^13.1.0",
"optimize-css-assets-webpack-plugin": "^5.0.0",
"postcss-loader": "^2.0.8",
"postcss-nested": "^3.0.0",
"postcss-loader": "^3.0.0",
"postcss-nested": "^4.1.0",
"postcss-scss": "^2.0.0",
"remove-debug-loader": "^0.2.2",
"reset.css": "^2.0.2",
"sass-loader": "^7.0.3",
"sinon": "^6.1.4",
"style-loader": "^0.21.0",
"sass-loader": "^7.1.0",
"sinon": "^7.1.1",
"style-loader": "^0.23.1",
"supertest": "^3.1.0",
"uglifyjs-webpack-plugin": "^1.1.5",
"uglifyjs-webpack-plugin": "^2.0.1",
"url-loader": "^1.0.1",
"webpack": "^4.5.0",
"webpack-bundle-analyzer": "^2.11.1",
"webpack-cli": "^2.0.14",
"webpack-dev-middleware": "^3.1.2",
"webpack-hot-middleware": "^2.21.0",
"webpack": "^4.25.1",
"webpack-bundle-analyzer": "^3.0.3",
"webpack-cli": "^3.1.2",
"webpack-dev-middleware": "^3.4.0",
"webpack-hot-middleware": "^2.24.3",
"webpack-hot-server-middleware": "^0.5.0",
"webpack-node-externals": "^1.6.0"
},
"dependencies": {
"@babel/runtime": "^7.1.5",
"babel-plugin-react-css-modules": "^3.4.2",
"babel-runtime": "^6.26.0",
"body-parser": "^1.18.2",
"classnames": "^2.2.5",
"debug": "^3.1.0",
"debug": "^4.1.0",
"express": "^4.16.2",
"immutability-helper": "^2.7.1",
"lodash": "^4.17.4",
Expand All @@ -79,14 +87,14 @@
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-helmet": "^5.2.0",
"react-hot-loader": "^4.3.3",
"react-hot-loader": "^4.3.12",
"react-redux": "^5.0.6",
"react-router": "^4.3.1",
"react-router-dom": "^4.3.1",
"redux": "^4.0.0",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0",
"superagent": "^3.8.2"
"superagent": "^4.0.0-beta.5"
},
"description": "This boilerplate would help you build a react/redux/react-router isomorphic/universal web app",
"repository": {
Expand Down Expand Up @@ -115,18 +123,22 @@
"!test/helpers/**/*"
],
"require": [
"babel-register",
"@babel/register",
"ignore-styles",
"css-modules-require-hook/preset",
"./src/enzymeSetup.js"
],
"babel": "inherit"
]
},
"nyc": {
"require": [
"babel-register"
"@babel/register"
],
"sourceMap": false,
"instrument": false
}
},
"sideEffects": [
"*.scss",
"src/entries/main.js",
"src/entries/anotherEntry.js"
]
}
4 changes: 2 additions & 2 deletions src/entries/template.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { hydrate } from 'react-dom';
import { Provider } from 'react-redux';
import { BrowserRouter as Router, browserHistory } from 'react-router-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import configureStore from '../configureStore';

/**
Expand All @@ -27,7 +27,7 @@ export default function mount(Routes, rootReducer) {

hydrate(
<Provider store={store}>
<Router history={browserHistory}>
<Router>
<Routes />
</Router>
</Provider>,
Expand Down
8 changes: 6 additions & 2 deletions src/server/__tests__/layout.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ const head = {

const mockClientStats = {
publicPath: '/',
assetsByChunkName: {
main: ['main.js', 'main.css'],
entrypoints: {
main: {
assets: [
'', '',
],
},
},
};

Expand Down
2 changes: 1 addition & 1 deletion src/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import express from 'express';
import stdout from '../stdout';
import apiMiddleware from './api';
import renderer from './renderer';
import stats from '../../compilation-stats.json'; // eslint-disable-line
import stats from 'compilation-stats.json'; // eslint-disable-line

const debug = stdout('server:index');

Expand Down
54 changes: 7 additions & 47 deletions src/server/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,52 +27,15 @@ function genTag(targetPath, type) {
return res;
}

function getAssetInfo(asset, publicPath) {
let js;
let css;
if (Array.isArray(asset)) {
js = [];
css = [];
asset.forEach((a) => {
if (/\.js$/.test(a)) { js.push(path.join(publicPath, a)); }
if (/\.css/.test(a)) { css.push(path.join(publicPath, a)); }
});
} else {
js = asset ? path.join(publicPath, asset) : '';
}
return { js, css };
}

function parseStats(clientStats, currentEntry) {
const { assetsByChunkName, publicPath } = clientStats;
const currentEntryAsset = assetsByChunkName[currentEntry] || '';
// check each assetsByChunkName
// treat any chunk name includes currentEntry
// as related asset
const relatedAssets = Object.keys(assetsByChunkName).map((k) => {
const res = k.indexOf(currentEntry) > -1 && k !== currentEntry ? assetsByChunkName[k] : '';
return res;
});
debug('here', relatedAssets);
return {
main: getAssetInfo(currentEntryAsset, publicPath),
related: relatedAssets.map(asset => getAssetInfo(asset, publicPath)),
};
}

function renderFullPage(content, reduxState, head, currentEntry, clientStats) {
const {
main: targetAssets,
related: relatedAssets,
} = parseStats(clientStats, currentEntry);
const { entrypoints, publicPath } = clientStats;
const targetAssets = entrypoints[currentEntry].assets.map(a => path.join(publicPath, a));
debug('targetAssets', targetAssets);
const targetJS = genTag(targetAssets.js, 'JS');
const targetCSS = genTag(targetAssets.css, 'CSS');
let relatedCSS = '';
let relatedJS = '';
relatedAssets.map((r) => {
if (r.js) relatedJS += genTag(r.js, 'JS');
if (r.css) relatedCSS += genTag(r.css, 'CSS');
let targetJS = '';
let targetCSS = '';
targetAssets.map((a) => {
if (/\.js$/.test(a)) { targetJS += genTag(a, 'JS'); }
if (/\.css$/.test(a)) { targetCSS += genTag(a, 'CSS'); }
return false;
});

Expand All @@ -90,7 +53,6 @@ function renderFullPage(content, reduxState, head, currentEntry, clientStats) {
<link rel="apple-touch-icon" href=${touchicon} />
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet" />
${relatedCSS}
${targetCSS}
<script type="text/javascript" charSet="utf-8">
Expand All @@ -99,8 +61,6 @@ function renderFullPage(content, reduxState, head, currentEntry, clientStats) {
</head>
<body>
<div id="app-mount-point">${content}</div>
${relatedJS}
<!-- entry script generated by webpack -->
${targetJS}
</body>
</html>
Expand Down
Loading

0 comments on commit 82b1508

Please sign in to comment.