add preact with webpack

This commit is contained in:
Thomas Ruoff
2017-02-15 00:46:54 +01:00
parent 316d05790b
commit 7668fc3837
15 changed files with 229 additions and 3 deletions

8
config/babel.js Normal file
View File

@@ -0,0 +1,8 @@
module.exports = {
presets: [
['es2015', {modules: false}]
],
plugins: [
['transform-react-jsx', {pragma: 'h'}]
]
};

47
config/setup.js Normal file
View File

@@ -0,0 +1,47 @@
const { join } = require('path');
const webpack = require('webpack');
const Dashboard = require('webpack-dashboard/plugin');
const Clean = require('clean-webpack-plugin');
const Copy = require('copy-webpack-plugin');
const HTML = require('html-webpack-plugin');
const uglify = require('./uglify');
const babel = require('./babel');
const root = join(__dirname, '..');
module.exports = isProd => {
// base plugins array
const plugins = [
new Clean(['dist'], { root }),
new Copy([{ context: 'webapp/static/', from: '**/*.*' }]),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(isProd ? 'production' : 'development')
}),
new HTML({ template: 'webapp/index.html' }),
new webpack.LoaderOptionsPlugin({
options: {
babel
}
})
];
if (isProd) {
plugins.push(
new webpack.LoaderOptionsPlugin({ minimize: true, debug: false }),
new webpack.optimize.UglifyJsPlugin(uglify)
);
} else {
// dev only
plugins.push(
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
new webpack.DefinePlugin({
__DEVELOPMENT__: !isProd
}),
new Dashboard()
);
}
return plugins;
};

16
config/uglify.js Normal file
View File

@@ -0,0 +1,16 @@
module.exports = {
output: {
comments: 0
},
compress: {
unused: 1,
warnings: 0,
comparisons: 1,
conditionals: 1,
negate_iife: 0, // <- for `LazyParseWebpackPlugin()`
dead_code: 1,
if_return: 1,
join_vars: 1,
evaluate: 1
}
};

46
config/webpack.js Normal file
View File

@@ -0,0 +1,46 @@
const { join } = require('path');
const setup = require('./setup');
const dist = join(__dirname, '../dist');
const exclude = /node_modules/;
module.exports = env => {
const isProd = env && env.production;
return {
entry: {
app: './webapp/index.js',
vendor: [
'preact'
]
},
output: {
path: dist,
filename: '[name].[hash].js',
publicPath: '/'
},
resolve: {
alias: {
'react': 'preact/aliases',
'react-dom': 'preact/aliases'
}
},
module: {
rules: [{
test: /\.jsx?$/,
exclude: exclude,
loader: 'babel-loader'
}]
},
plugins: setup(isProd),
devtool: !isProd && 'source-map',
devServer: {
contentBase: dist,
port: process.env.PORT || 5050,
historyApiFallback: true,
compress: isProd,
inline: !isProd,
hot: !isProd
}
};
};

View File

@@ -25,4 +25,6 @@ app.post('/generate/:template', (req, res) => {
}); });
}); });
app.use(express.static('dist'));
app.listen(5000); app.listen(5000);

View File

@@ -4,15 +4,31 @@
"description": "Generate pdfs based on a template", "description": "Generate pdfs based on a template",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --env.production --config config/webpack",
"start": "node index.js",
"watch": "webpack-dashboard -- webpack-dev-server --config config/webpack"
}, },
"author": "Thomas Ruoff <tomru@mail.id0.link>", "author": "Thomas Ruoff <tomru@mail.id0.link>",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"body-parser": "^1.16.1", "body-parser": "^1.16.1",
"express": "^4.14.1" "express": "^4.14.1",
"preact": "^7.2.0",
"preact-router": "^2.4.1"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^3.15.0" "babel-core": "^6.23.1",
"babel-loader": "^6.3.0",
"babel-plugin-transform-react-jsx": "^6.23.0",
"babel-preset-es2015": "^6.22.0",
"babel-preset-react": "^6.23.0",
"clean-webpack-plugin": "^0.1.15",
"copy-webpack-plugin": "^4.0.1",
"eslint": "^3.15.0",
"html-webpack-plugin": "^2.28.0",
"webpack": "^2.2.1",
"webpack-dashboard": "^0.3.0",
"webpack-dev-server": "^2.3.0"
} }
} }

13
webapp/index.html Normal file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>PDFer</title>
<meta name="application-name" content="PDFer">
</head>
<body>
<div id="root">
<div id="app">Loading</div>
</div>
</body>
</html>

19
webapp/index.js Normal file
View File

@@ -0,0 +1,19 @@
import { render } from 'preact';
function init() {
const App = require('./views').default;
render(App, document.getElementById('root'), document.getElementById('app'));
}
init();
if (process.env.NODE_ENV === 'production') {
console.log('for real now');
} else {
// use preact's devtools
require('preact/devtools');
// listen for HMR
if (module.hot) {
module.hot.accept('./views', init);
}
}

BIN
webapp/static/favicon.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

0
webapp/styles/styles.css Normal file
View File

View File

@@ -0,0 +1,10 @@
import { h } from 'preact';
import { Link } from 'preact-router';
export default function () {
return (
<header className="header">
<h1>PDFer</h1>
</header>
)
}

View File

@@ -0,0 +1,13 @@
import { h } from 'preact';
import Header from './Header';
export default function (props) {
return (
<div id="app">
<Header />
<div id="content">
{ props.children }
</div>
</div>
);
}

15
webapp/views/index.js Normal file
View File

@@ -0,0 +1,15 @@
import { h } from 'preact'
import { Router } from 'preact-router';
import Home from './pages/Home';
import Layout from './components/Layout';
import Error404 from './pages/404';
export default (
<Layout>
<Router>
<Home path="/" />
<Error404 default />
</Router>
</Layout>
);

10
webapp/views/pages/404.js Normal file
View File

@@ -0,0 +1,10 @@
import { h } from 'preact';
export default function (props) {
return (
<div>
<h2>No hope!</h2>
<p>Not sure what you desire, but look for somewhere else...</p>
</div>
);
}

View File

@@ -0,0 +1,11 @@
import { h } from 'preact';
export default function (props) {
return (
<div>
<h1>Home</h1>
<p>This is the home page.</p>
<p>Anything is insane</p>
</div>
);
}