diff --git a/package.json b/package.json index 65cc7da..49e2475 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "portfolio", "main": "index.js", "scripts": { - "build": "NODE_ENV=production webpack -p --progress --config webpack.prod.config.js", + "build": "NODE_ENV=production webpack -p --progress", "start": "NODE_ENV=production node ./src/server.js", "dev": "NODE_ENV=development babel-node ./src/server.js --presets es2015,stage-2 ./srcserver.js" }, @@ -25,7 +25,8 @@ "node-sass": "^4.9.0", "react": "^16.7.0", "react-dom": "^16.7.0", - "react-router-dom": "^4.1.1" + "react-router-dom": "^4.1.1", + "webpack-node-externals": "^1.7.2" }, "devDependencies": { "babel-cli": "^6.26.0", diff --git a/src/app-client.js b/src/app-client.js index 02275e5..d6eb8d8 100644 --- a/src/app-client.js +++ b/src/app-client.js @@ -5,7 +5,7 @@ import {App} from './components'; const AppClient = () => ( - + ) diff --git a/src/components/App.js b/src/components/App.js index f3aef34..b629b41 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,16 +1,43 @@ -import React from 'react'; -import { Route, Switch } from 'react-router-dom'; -import { NotFoundWrapper } from '.'; -import { MainContainer, PostContainer } from '../containers'; +import { NotFoundWrapper } from '.' +import React, { Component } from 'react' +import routes from '../utils/routes' +import { Route, Switch } from 'react-router-dom' -export const App = () => ( -
- - - - - -
-); +class App extends Component { + render() { + return ( +
+ + {routes.map(({ path, exact, component: C, ...rest }) => ( + ( + + )} + /> + ))} + } /> + +
+ ) + } +} -export default App; +// import React from 'react'; +// import { Route, Switch } from 'react-router-dom'; +// import { NotFoundWrapper } from '.'; +// import { MainContainer, PostContainer } from '../containers'; +// +// export const App = () => ( +//
+// +// +// +// +// +//
+// ); +// +// export default App; diff --git a/src/server.js b/src/server.js index 2b0a6a1..8500d6e 100644 --- a/src/server.js +++ b/src/server.js @@ -21,23 +21,23 @@ var dataStub = {"posts": [], "other": []}; fs.writeFileSync(filename, JSON.stringify(dataStub)); -// initalize webpack dev middleware if in development context -if (process.env.NODE_ENV === 'development') { - var webpack = require('webpack') - var config = require('../webpack.config') - - var devMiddleware = require('webpack-dev-middleware') - var hotDevMiddleware = require('webpack-hot-middleware') - var compiler = webpack(config) - var devMiddlewareConfig = { - noInfo: true, - stats: {colors: true}, - publicPath: config.output.publicPath - } - - app.use(devMiddleware(compiler, devMiddlewareConfig)) - app.use(hotDevMiddleware(compiler)) -} +// // initalize webpack dev middleware if in development context +// if (process.env.NODE_ENV === 'development') { +// var webpack = require('webpack') +// var config = require('../webpack.config') +// +// var devMiddleware = require('webpack-dev-middleware') +// var hotDevMiddleware = require('webpack-hot-middleware') +// var compiler = webpack(config) +// var devMiddlewareConfig = { +// noInfo: true, +// stats: {colors: true}, +// publicPath: config.output.publicPath +// } +// +// app.use(devMiddleware(compiler, devMiddlewareConfig)) +// app.use(hotDevMiddleware(compiler)) +// } require('./utils/scanner')(); diff --git a/src/utils/api.js b/src/utils/api.js index d3478d4..7965a9f 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -1,56 +1,18 @@ -const data = require('./data.json'); -const api = require('express').Router(); -const fs = require('fs'); -const path = require('path'); -const config = require('../../config.json'); +import data from './data.json' -api.get('/blog', (req, res) => { - res.set('Cache-Control', 'no-cache'); - data.posts.sort((a,b) => { - return new Date(b.published) - new Date(a.published); - }) - res.json(data.posts); -}); +export function getData(path = ''){ + if (path === ''){ + return data + } else { + fileName = '../../content/' + path + return readFile(fileName) + } +} -api.get('/about', (req, res) => { - const renderPath = path.join(process.cwd(), '/renders', 'about.html'); - res.set('Cache-Control', 'max-age=86400'); - fs.readFile(renderPath, 'utf8', (err, data) => { - if (err) { - res.json({ - error: 404 - }); - } else { - res.json({ - body: data, - }); - } +function readFile(fileName, type) { + return new Promise(function(resolve, reject){ + fs.readFile(fileName, (err, data) => { + err ? reject(err) : resolve(data); + }); }); -}); - -api.get('/post/:postname', (req, res) => { - res.set('Cache-Control', 'no-cache'); - const postname = req.params.postname; - const post = data.posts.find((el) => { - return el.filename === postname - }); - - const renderPath = path.join(process.cwd(), '/renders', postname + '.html'); - fs.readFile(renderPath, 'utf8', (err, data) => { - if (err) { - res.json({ - error: 404 - }); - } else { - res.json({ - published: post.published, - link: post.link, - title: post.title, - body: data, - }); - } - }); -}); - - -module.exports = api; +} diff --git a/src/utils/routes.js b/src/utils/routes.js index 5770a7a..9343294 100644 --- a/src/utils/routes.js +++ b/src/utils/routes.js @@ -17,9 +17,6 @@ const routes = [ getData: (path = '') => getData( path.split('/').pop() ) - }, - { - component: NotFoundWrapper, } ] diff --git a/src/utils/serverRender.js b/src/utils/serverRender.js index 1b54d94..cd1d243 100644 --- a/src/utils/serverRender.js +++ b/src/utils/serverRender.js @@ -10,6 +10,17 @@ function serverRender(req, res) { const activeRoute = routes.find((route) => matchPath(req.url, route)) || {} + const promise = activeRoute.fetchInitialData + ? activeRoute.fetchInitialData(req.path) + : Promise.resolve() + + promise.then((data) => { + const markup = renderToString( + + + , + ); + }) let markup = ''; let status = 200; diff --git a/webpack.config.js b/webpack.config.js index da607ab..053ba0e 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,74 +1,102 @@ const { resolve, join } = require('path') const webpack = require('webpack') -const ManifestPlugin = require('webpack-manifest-plugin'); +const UglifyJsPlugin = require("uglifyjs-webpack-plugin") +const MiniCssExtractPlugin = require("mini-css-extract-plugin") +const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin") +const CompressionPlugin = require("compression-webpack-plugin") +const ManifestPlugin = require('webpack-manifest-plugin') +const CleanWebpackPlugin = require('clean-webpack-plugin') +const nodeExternals = require('webpack-node-externals') -const config = { - mode: 'development', - devtool: 'cheap-eval-source-map', +const commonConfig = { + rules: [ + { + test: /\.js$/, + use: [ + 'babel-loader' + ], + exclude: '/node_modules/' + }, + { + test: /\.scss$/, + use: [ + MiniCssExtractPlugin.loader, + { + loader: 'css-loader', + options: { + modules: true, + importLoaders: 2, + localIdentName: '[name]__[local]___[hash:base64:5]' + } + }, + { + loader: "postcss-loader" + }, + { + loader: 'sass-loader' + } + ] + }, + { + test: /\.(png|jpg)$/, + exclude: /node_modules/, + loader: 'url-loader', + options: { + limit: 8192 + } + }, + ] +} + +const browserConfig = { + mode: 'production', context: resolve(__dirname, 'src'), entry: { bundle: [ - 'webpack-hot-middleware/client', './app-client.js' ] }, output: { - path: resolve(__dirname,'public/static'), - filename: 'bundle.js', + path: resolve(__dirname, 'public/static'), + filename: '[name].[contenthash].js', publicPath: '/static/' }, - module: { - rules: [ - { - test: /\.js$/, - use: [ - 'babel-loader' - ], - exclude: '/node_modules/' - }, - { - test: /\.scss$/, - use: [ - { - loader: "style-loader" - }, - { - loader: 'css-loader', - options: { - modules: true, - importLoaders: 2, - localIdentName: '[name]__[local]___[hash:base64:5]' - } - }, - { - loader: "postcss-loader" - }, - { - loader: "sass-loader" - } - ] - }, - { - test: /\.(png|jpg)$/, - exclude: /node_modules/, - loader: 'url-loader' - }, - { - test: /\.(html)$/, - use: { - loader: 'html-loader', - options: { - attrs: [':data-src'] - } - } - }, + module: commonConfig, + optimization: { + minimizer: [ + new UglifyJsPlugin({ + cache: true, + parallel: true, + sourceMap: true // set to true if you want JS source maps + }), + new OptimizeCSSAssetsPlugin({}) ] }, plugins: [ - new webpack.HotModuleReplacementPlugin(), - new webpack.NoEmitOnErrorsPlugin(), - new webpack.NamedModulesPlugin(), - new ManifestPlugin({'writeToFileEmit': true}), + new webpack.DefinePlugin({__isBrowser__: "true"}), + new CleanWebpackPlugin(['dist', 'public/static'], {}), + new MiniCssExtractPlugin({filename: '[name].[contenthash].css'}), + new CompressionPlugin({}), + new ManifestPlugin(), ] } -module.exports = config + +const serverConfig = { + entry: './src/server.js', + target: 'node', + externals: [nodeExternals()], + output: { + path: __dirname, + filename: 'server.js', + publicPath: '/' + }, + module: commonConfig, + plugins: [ + new webpack.DefinePlugin({ + __isBrowser__: "false" + }), + new MiniCssExtractPlugin({filename: '[name].[contenthash].css'}), + ] +} + +module.exports = [browserConfig, serverConfig] diff --git a/webpack.prod.config.js b/webpack.prod.config.js deleted file mode 100644 index 2e91441..0000000 --- a/webpack.prod.config.js +++ /dev/null @@ -1,80 +0,0 @@ -const { resolve, join } = require('path') -const webpack = require('webpack') -const UglifyJsPlugin = require("uglifyjs-webpack-plugin") -const MiniCssExtractPlugin = require("mini-css-extract-plugin") -const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin") -const CompressionPlugin = require("compression-webpack-plugin") -const ManifestPlugin = require('webpack-manifest-plugin') -const CleanWebpackPlugin = require('clean-webpack-plugin') - -const config = { - mode: 'production', - context: resolve(__dirname, 'src'), - entry: { - bundle: [ - './app-client.js' - ] - }, - output: { - path: resolve(__dirname, 'public/static'), - filename: '[name].[contenthash].js', - publicPath: '/static/' - }, - module: { - rules: [ - { - test: /\.js$/, - use: [ - 'babel-loader' - ], - exclude: '/node_modules/' - }, - { - test: /\.scss$/, - use: [ - MiniCssExtractPlugin.loader, - { - loader: 'css-loader', - options: { - modules: true, - importLoaders: 2, - localIdentName: '[name]__[local]___[hash:base64:5]' - } - }, - { - loader: "postcss-loader" - }, - { - loader: 'sass-loader' - } - ] - }, - { - test: /\.(png|jpg)$/, - exclude: /node_modules/, - loader: 'url-loader', - options: { - limit: 8192 - } - }, - ] - }, - optimization: { - minimizer: [ - new UglifyJsPlugin({ - cache: true, - parallel: true, - sourceMap: true // set to true if you want JS source maps - }), - new OptimizeCSSAssetsPlugin({}) - ] - }, - plugins: [ - new CleanWebpackPlugin(['dist', 'public/static'], {}), - new MiniCssExtractPlugin({filename: '[name].[contenthash].css'}), - new CompressionPlugin({}), - new ManifestPlugin(), - ] -} - -module.exports = config diff --git a/yarn.lock b/yarn.lock index 69724f9..822258c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6735,6 +6735,11 @@ webpack-manifest-plugin@^2.0.3: lodash ">=3.5 <5" tapable "^1.0.0" +webpack-node-externals@^1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-1.7.2.tgz#6e1ee79ac67c070402ba700ef033a9b8d52ac4e3" + integrity sha512-ajerHZ+BJKeCLviLUUmnyd5B4RavLF76uv3cs6KNuO8W+HuQaEs0y0L7o40NQxdPy5w0pcv8Ew7yPUAQG0UdCg== + webpack-sources@^1.0.1, webpack-sources@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.1.0.tgz#a101ebae59d6507354d71d8013950a3a8b7a5a54"