initial commit, get frontend code in
This commit is contained in:
commit
060a7c913a
|
@ -0,0 +1,8 @@
|
||||||
|
node_modules/
|
||||||
|
bower_components/
|
||||||
|
output/
|
||||||
|
dist/
|
||||||
|
static/dist
|
||||||
|
.psci_modules
|
||||||
|
npm-debug.log
|
||||||
|
**DS_Store
|
|
@ -0,0 +1 @@
|
||||||
|
15098
|
|
@ -0,0 +1,24 @@
|
||||||
|
Copyright (c) 2016, Alexander C. Mingoia
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the <organization> nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,38 @@
|
||||||
|
# pux-starter-app
|
||||||
|
|
||||||
|
Starter [Pux](https://github.com/alexmingoia/purescript-pux/) application using
|
||||||
|
webpack with hot-reloading and time-travel debug using
|
||||||
|
[pux-devtool](https://github.com/alexmingoia/pux-devtool).
|
||||||
|
|
||||||
|
See the [Guide](https://alexmingoia.github.io/purescript-pux) for help learning
|
||||||
|
Pux.
|
||||||
|
|
||||||
|
![Pux starter app animation](support/pux-starter-app.gif)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone git://github.com/alexmingoia/pux-starter-app.git example
|
||||||
|
cd example
|
||||||
|
npm install
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
Visit `http://localhost:3000` in your browser, edit `src/purs/Layout.purs`
|
||||||
|
and watch the magic!
|
||||||
|
|
||||||
|
## Available scripts
|
||||||
|
|
||||||
|
### watch
|
||||||
|
|
||||||
|
`npm start` or `npm run watch` will start a development server, which
|
||||||
|
hot-reloads your application when sources changes.
|
||||||
|
|
||||||
|
### serve
|
||||||
|
|
||||||
|
`npm run serve` serves your application without watching for changes or
|
||||||
|
hot-reloading.
|
||||||
|
|
||||||
|
### build
|
||||||
|
|
||||||
|
`npm run build` bundles and minifies your application to run in production mode.
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"name": "pux-starter-app",
|
||||||
|
"homepage": "https://github.com/alexmingoia/pux-starter-app",
|
||||||
|
"authors": [
|
||||||
|
"Alex Mingoia <talk@alexmingoia.com>"
|
||||||
|
],
|
||||||
|
"description": "Starter Pux application using webpack with hot-reloading.",
|
||||||
|
"main": "support/index.js",
|
||||||
|
"license": "BSD3",
|
||||||
|
"dependencies": {
|
||||||
|
"purescript-pux": "^7.0.0",
|
||||||
|
"purescript-pux-devtool": "^4.1.0",
|
||||||
|
"purescript-argonaut": "^2.0.0",
|
||||||
|
"purescript-affjax": "^3.0.2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
"name": "pux-starter-app",
|
||||||
|
"version": "9.0.0",
|
||||||
|
"description": "Starter Pux application using webpack with hot-reloading.",
|
||||||
|
"main": "support/index.js",
|
||||||
|
"keywords": [
|
||||||
|
"pux",
|
||||||
|
"purescript-pux",
|
||||||
|
"boilerplate",
|
||||||
|
"starter-app"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"postinstall": "bower cache clean && bower install",
|
||||||
|
"clean": "rimraf static/dist && rimraf dist && rimraf output",
|
||||||
|
"build": "npm run clean && webpack --config ./webpack.production.config.js --progress --profile --colors",
|
||||||
|
"watch": "npm run clean && node ./webpack.config.js",
|
||||||
|
"serve": "http-server static --cors -p 3000",
|
||||||
|
"start": "npm run watch",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/alexmingoia/pux-starter-app.git"
|
||||||
|
},
|
||||||
|
"author": "Alexander C. Mingoia",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/alexmingoia/pux-starter-app/issues"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"bower": "^1.7.9",
|
||||||
|
"connect-history-api-fallback": "^1.2.0",
|
||||||
|
"express": "^4.13.4",
|
||||||
|
"html-webpack-plugin": "^2.15.0",
|
||||||
|
"http-server": "^0.9.0",
|
||||||
|
"purescript": "^0.10.1",
|
||||||
|
"purescript-psa": "^0.3.9",
|
||||||
|
"purs-loader": "^2.0.0",
|
||||||
|
"react": "^15.0.0",
|
||||||
|
"react-dom": "^15.0.0",
|
||||||
|
"rimraf": "^2.5.2",
|
||||||
|
"webpack": "^2.1.0-beta.25"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"source-map-loader": "^0.1.5",
|
||||||
|
"webpack-dev-middleware": "^1.8.3",
|
||||||
|
"webpack-hot-middleware": "^2.12.2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
module App.BlogIndex where
|
||||||
|
|
||||||
|
import Control.Monad.Aff (attempt)
|
||||||
|
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
|
||||||
|
import Data.Either (Either(Left, Right), either)
|
||||||
|
import DOM (DOM)
|
||||||
|
import Network.HTTP.Affjax (AJAX, get)
|
||||||
|
import Prelude (($), bind, map, const, show, (<>), pure, (<<<))
|
||||||
|
import Pux (EffModel, noEffects)
|
||||||
|
import Pux.Html (Html, br, div, h1, ol, li, button, text, span, p)
|
||||||
|
import Pux.Html.Attributes (key, className)
|
||||||
|
import Pux.Html.Events (onClick)
|
||||||
|
|
||||||
|
data Action = RequestPosts
|
||||||
|
| ReceivePosts (Either String Posts)
|
||||||
|
|
||||||
|
type State =
|
||||||
|
{ posts :: Posts
|
||||||
|
, status :: String }
|
||||||
|
|
||||||
|
data Post = Post
|
||||||
|
{ title :: String
|
||||||
|
, link :: String
|
||||||
|
, summary :: String
|
||||||
|
, date :: String }
|
||||||
|
|
||||||
|
type Posts = Array Post
|
||||||
|
|
||||||
|
instance decodeJsonPost :: DecodeJson Post where
|
||||||
|
decodeJson json = do
|
||||||
|
obj <- decodeJson json
|
||||||
|
title <- obj .? "title"
|
||||||
|
link <- obj .? "link"
|
||||||
|
summ <- obj .? "summary"
|
||||||
|
date <- obj .? "date"
|
||||||
|
pure $ Post { title: title, link: link, summary: summ, date: date }
|
||||||
|
|
||||||
|
init :: State
|
||||||
|
init =
|
||||||
|
{ posts: []
|
||||||
|
, status: "Loading..." }
|
||||||
|
|
||||||
|
update :: Action -> State -> EffModel State Action (ajax :: AJAX, dom :: DOM)
|
||||||
|
update (ReceivePosts (Left err)) state =
|
||||||
|
noEffects $ state { status = ("error: " <> err) }
|
||||||
|
update (ReceivePosts (Right posts)) state =
|
||||||
|
noEffects $ state { posts = posts, status = "Posts" }
|
||||||
|
update RequestPosts state =
|
||||||
|
{ state: state { status = "Fetching posts..." }
|
||||||
|
, effects: [ do
|
||||||
|
res <- attempt $ get "/api/blog/posts"
|
||||||
|
let decode r = decodeJson r.response :: Either String Posts
|
||||||
|
let posts = either (Left <<< show) decode res
|
||||||
|
pure $ ReceivePosts posts
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
post :: Post -> Html Action
|
||||||
|
post (Post state) =
|
||||||
|
div
|
||||||
|
[ className "col s4" ]
|
||||||
|
[ div
|
||||||
|
[ className "card pink lighten-1" ]
|
||||||
|
[ div
|
||||||
|
[ className "card-content black-text" ]
|
||||||
|
[ span [ className "card-title" ] [ text state.title ]
|
||||||
|
, br [] []
|
||||||
|
, p [] [ text ("Posted on: " <> state.date) ]
|
||||||
|
, span [] [ text state.summary ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
view :: State -> Html Action
|
||||||
|
view state =
|
||||||
|
div
|
||||||
|
[]
|
||||||
|
[ h1 [] [ text state.status ]
|
||||||
|
, button [ onClick (const RequestPosts) ] [ text "Fetch posts" ]
|
||||||
|
, div [ className "row" ] $ map post state.posts ]
|
|
@ -0,0 +1,40 @@
|
||||||
|
module App.Counter where
|
||||||
|
|
||||||
|
import Prelude ((+), (-), const, show)
|
||||||
|
import Pux.Html (Html, a, br, div, span, text)
|
||||||
|
import Pux.Html.Attributes (className, href)
|
||||||
|
import Pux.Html.Events (onClick)
|
||||||
|
|
||||||
|
data Action = Increment | Decrement
|
||||||
|
|
||||||
|
type State = Int
|
||||||
|
|
||||||
|
init :: State
|
||||||
|
init = 0
|
||||||
|
|
||||||
|
update :: Action -> State -> State
|
||||||
|
update Increment state = state + 1
|
||||||
|
update Decrement state = state - 1
|
||||||
|
|
||||||
|
view :: State -> Html Action
|
||||||
|
view state =
|
||||||
|
div
|
||||||
|
[ className "row" ]
|
||||||
|
[ div
|
||||||
|
[ className "col s4 offset-s4" ]
|
||||||
|
[ div
|
||||||
|
[ className "card blue-grey darken-1" ]
|
||||||
|
[ div
|
||||||
|
[ className "card-content white-text" ]
|
||||||
|
[ span [ className "card-title" ] [ text "Counter" ]
|
||||||
|
, br [] []
|
||||||
|
, span [] [ text (show state) ]
|
||||||
|
]
|
||||||
|
, div
|
||||||
|
[ className "card-action" ]
|
||||||
|
[ a [ onClick (const Increment), href "#" ] [ text "Increment" ]
|
||||||
|
, a [ onClick (const Decrement), href "#" ] [ text "Decrement" ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
|
@ -0,0 +1,61 @@
|
||||||
|
module App.Layout where
|
||||||
|
|
||||||
|
import App.BlogIndex as BlogIndex
|
||||||
|
import App.Counter as Counter
|
||||||
|
import App.Routes (Route(..))
|
||||||
|
import DOM (DOM)
|
||||||
|
import Network.HTTP.Affjax (AJAX)
|
||||||
|
import Prelude (($), (#), map, pure)
|
||||||
|
import Pux (EffModel, noEffects, mapEffects, mapState)
|
||||||
|
import Pux.Html (Html, div, h1, nav, text)
|
||||||
|
import Pux.Html.Attributes (className, id_, role)
|
||||||
|
import Pux.Router (link)
|
||||||
|
|
||||||
|
data Action
|
||||||
|
= Child (Counter.Action)
|
||||||
|
| BIChild (BlogIndex.Action)
|
||||||
|
| PageView Route
|
||||||
|
|
||||||
|
type State =
|
||||||
|
{ route :: Route
|
||||||
|
, count :: Counter.State
|
||||||
|
, bistate :: BlogIndex.State }
|
||||||
|
|
||||||
|
init :: State
|
||||||
|
init =
|
||||||
|
{ route: NotFound
|
||||||
|
, count: Counter.init
|
||||||
|
, bistate: BlogIndex.init }
|
||||||
|
|
||||||
|
update :: Action -> State -> EffModel State Action (ajax :: AJAX, dom :: DOM)
|
||||||
|
update (PageView route) state = noEffects $ state { route = route }
|
||||||
|
update (BIChild action) state = BlogIndex.update action state.bistate
|
||||||
|
# mapState (state { bistate = _ })
|
||||||
|
# mapEffects BIChild
|
||||||
|
update (Child action) state = noEffects $ state { count = Counter.update action state.count }
|
||||||
|
|
||||||
|
view :: State -> Html Action
|
||||||
|
view state =
|
||||||
|
div
|
||||||
|
[]
|
||||||
|
[ navbar state
|
||||||
|
, div
|
||||||
|
[ className "container" ]
|
||||||
|
[ page state.route state ]
|
||||||
|
]
|
||||||
|
|
||||||
|
navbar :: State -> Html Action
|
||||||
|
navbar state =
|
||||||
|
nav
|
||||||
|
[ className "light-blue lighten-1", role "navigation" ]
|
||||||
|
[ div
|
||||||
|
[ className "nav-wrapper container" ]
|
||||||
|
[ link "/" [ className "brand-logo", id_ "logo-container" ] [ text "Christine Dodrill" ] ]
|
||||||
|
]
|
||||||
|
|
||||||
|
page :: Route -> State -> Html Action
|
||||||
|
page NotFound _ = h1 [] [ text "not found" ]
|
||||||
|
page Home state = map Child $ Counter.view state.count
|
||||||
|
page Resume state = h1 [] [ text "Christine Dodrill" ]
|
||||||
|
page BlogIndex state = map BIChild $ BlogIndex.view state.bistate
|
||||||
|
page _ _ = h1 [] [ text "not implemented yet" ]
|
|
@ -0,0 +1,46 @@
|
||||||
|
module Main where
|
||||||
|
|
||||||
|
import App.Routes (match)
|
||||||
|
import App.Layout (Action(PageView), State, view, update)
|
||||||
|
import Control.Bind ((=<<))
|
||||||
|
import Control.Monad.Eff (Eff)
|
||||||
|
import DOM (DOM)
|
||||||
|
import Network.HTTP.Affjax (AJAX)
|
||||||
|
import Prelude (bind, pure)
|
||||||
|
import Pux (App, Config, CoreEffects, fromSimple, renderToDOM, start)
|
||||||
|
import Pux.Devtool (Action, start) as Pux.Devtool
|
||||||
|
import Pux.Router (sampleUrl)
|
||||||
|
import Signal ((~>))
|
||||||
|
|
||||||
|
type AppEffects = (dom :: DOM, ajax :: AJAX)
|
||||||
|
|
||||||
|
-- | App configuration
|
||||||
|
config :: forall eff. State -> Eff (dom :: DOM | eff) (Config State Action AppEffects)
|
||||||
|
config state = do
|
||||||
|
-- | Create a signal of URL changes.
|
||||||
|
urlSignal <- sampleUrl
|
||||||
|
|
||||||
|
-- | Map a signal of URL changes to PageView actions.
|
||||||
|
let routeSignal = urlSignal ~> \r -> PageView (match r)
|
||||||
|
|
||||||
|
pure
|
||||||
|
{ initialState: state
|
||||||
|
, update: update
|
||||||
|
, view: view
|
||||||
|
, inputs: [routeSignal] }
|
||||||
|
|
||||||
|
-- | Entry point for the browser.
|
||||||
|
main :: State -> Eff (CoreEffects AppEffects) (App State Action)
|
||||||
|
main state = do
|
||||||
|
app <- start =<< config state
|
||||||
|
renderToDOM "#app" app.html
|
||||||
|
-- | Used by hot-reloading code in support/index.js
|
||||||
|
pure app
|
||||||
|
|
||||||
|
-- | Entry point for the browser with pux-devtool injected.
|
||||||
|
debug :: State -> Eff (CoreEffects AppEffects) (App State (Pux.Devtool.Action Action))
|
||||||
|
debug state = do
|
||||||
|
app <- Pux.Devtool.start =<< config state
|
||||||
|
renderToDOM "#app" app.html
|
||||||
|
-- | Used by hot-reloading code in support/index.js
|
||||||
|
pure app
|
|
@ -0,0 +1,8 @@
|
||||||
|
module App.NotFound where
|
||||||
|
|
||||||
|
import Pux.Html (Html, (#), div, h2, text)
|
||||||
|
|
||||||
|
view :: forall state action. state -> Html action
|
||||||
|
view state =
|
||||||
|
div # do
|
||||||
|
h2 # text "404 Not Found"
|
|
@ -0,0 +1,21 @@
|
||||||
|
module App.Routes where
|
||||||
|
|
||||||
|
import Control.Alt ((<|>))
|
||||||
|
import Control.Apply ((<*), (*>))
|
||||||
|
import Data.Functor ((<$))
|
||||||
|
import Data.Maybe (fromMaybe)
|
||||||
|
import Prelude (($), (<$>))
|
||||||
|
import Pux.Router (param, router, lit, str, end)
|
||||||
|
|
||||||
|
data Route = Home
|
||||||
|
| Resume
|
||||||
|
| StaticPage String
|
||||||
|
| BlogIndex
|
||||||
|
| BlogPost String
|
||||||
|
| NotFound
|
||||||
|
|
||||||
|
match :: String -> Route
|
||||||
|
match url = fromMaybe NotFound $ router url $
|
||||||
|
Home <$ end
|
||||||
|
<|>
|
||||||
|
BlogIndex <$ lit "blog" <* end
|
|
@ -0,0 +1,7 @@
|
||||||
|
body {
|
||||||
|
font-family: 'Source Sans Pro', 'Trebuchet MS', 'Lucida Grande', 'Helvetica Neue', sans-serif;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
font-size: 14px;
|
||||||
|
letter-spacing: .2px;
|
||||||
|
text-size-adjust: 100
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>Pux Starter App</title>
|
||||||
|
|
||||||
|
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/css/materialize.min.css">
|
||||||
|
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.min.js"></script>
|
||||||
|
<link href="/app.css" rel="stylesheet" type="text/css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
var Main = require('../src/Main.purs');
|
||||||
|
var initialState = require('../src/Layout.purs').init;
|
||||||
|
var debug = process.env.NODE_ENV === 'development'
|
||||||
|
|
||||||
|
if (module.hot) {
|
||||||
|
var app = Main[debug ? 'debug' : 'main'](window.puxLastState || initialState)();
|
||||||
|
app.state.subscribe(function (state) {
|
||||||
|
window.puxLastState = state;
|
||||||
|
});
|
||||||
|
module.hot.accept();
|
||||||
|
} else {
|
||||||
|
Main[debug ? 'debug' : 'main'](initialState)();
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 2.0 MiB |
|
@ -0,0 +1,102 @@
|
||||||
|
var path = require('path');
|
||||||
|
var webpack = require('webpack');
|
||||||
|
var HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
|
|
||||||
|
var port = process.env.PORT || 3000;
|
||||||
|
|
||||||
|
var config = {
|
||||||
|
entry: [
|
||||||
|
'webpack-hot-middleware/client?reload=true',
|
||||||
|
path.join(__dirname, 'support/index.js'),
|
||||||
|
],
|
||||||
|
devtool: 'cheap-module-eval-source-map',
|
||||||
|
output: {
|
||||||
|
path: path.resolve('./static/dist'),
|
||||||
|
filename: '[name].js',
|
||||||
|
publicPath: '/'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
loaders: [
|
||||||
|
{ test: /\.js$/, loader: 'source-map-loader', exclude: /node_modules|bower_components/ },
|
||||||
|
{
|
||||||
|
test: /\.purs$/,
|
||||||
|
loader: 'purs-loader',
|
||||||
|
exclude: /node_modules/,
|
||||||
|
query: {
|
||||||
|
psc: 'psa',
|
||||||
|
pscArgs: {
|
||||||
|
sourceMaps: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
'process.env.NODE_ENV': JSON.stringify('development')
|
||||||
|
}),
|
||||||
|
new webpack.optimize.OccurrenceOrderPlugin(true),
|
||||||
|
new webpack.LoaderOptionsPlugin({
|
||||||
|
debug: true
|
||||||
|
}),
|
||||||
|
new webpack.SourceMapDevToolPlugin({
|
||||||
|
filename: '[file].map',
|
||||||
|
moduleFilenameTemplate: '[absolute-resource-path]',
|
||||||
|
fallbackModuleFilenameTemplate: '[absolute-resource-path]'
|
||||||
|
}),
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
template: 'support/index.html',
|
||||||
|
inject: 'body',
|
||||||
|
filename: 'index.html'
|
||||||
|
}),
|
||||||
|
new webpack.HotModuleReplacementPlugin(),
|
||||||
|
new webpack.NoErrorsPlugin(),
|
||||||
|
],
|
||||||
|
resolveLoader: {
|
||||||
|
modules: [
|
||||||
|
path.join(__dirname, 'node_modules')
|
||||||
|
]
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
modules: [
|
||||||
|
'node_modules',
|
||||||
|
'bower_components'
|
||||||
|
],
|
||||||
|
extensions: ['.js', '.purs']
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// If this file is directly run with node, start the development server
|
||||||
|
// instead of exporting the webpack config.
|
||||||
|
if (require.main === module) {
|
||||||
|
var compiler = webpack(config);
|
||||||
|
var express = require('express');
|
||||||
|
var app = express();
|
||||||
|
|
||||||
|
// Use webpack-dev-middleware and webpack-hot-middleware instead of
|
||||||
|
// webpack-dev-server, because webpack-hot-middleware provides more reliable
|
||||||
|
// HMR behavior, and an in-browser overlay that displays build errors
|
||||||
|
app
|
||||||
|
.use(express.static('./static'))
|
||||||
|
.use(require('connect-history-api-fallback')())
|
||||||
|
.use(require("webpack-dev-middleware")(compiler, {
|
||||||
|
publicPath: config.output.publicPath,
|
||||||
|
stats: {
|
||||||
|
hash: false,
|
||||||
|
timings: false,
|
||||||
|
version: false,
|
||||||
|
assets: false,
|
||||||
|
errors: true,
|
||||||
|
colors: false,
|
||||||
|
chunks: false,
|
||||||
|
children: false,
|
||||||
|
cached: false,
|
||||||
|
modules: false,
|
||||||
|
chunkModules: false,
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
.use(require("webpack-hot-middleware")(compiler))
|
||||||
|
.listen(port);
|
||||||
|
} else {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
var path = require('path');
|
||||||
|
var webpack = require('webpack');
|
||||||
|
var HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: [ path.join(__dirname, 'support/index.js') ],
|
||||||
|
output: {
|
||||||
|
path: path.resolve('./static/dist'),
|
||||||
|
filename: '[name]-[hash].min.js',
|
||||||
|
publicPath: '/dist/'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
loaders: [
|
||||||
|
{
|
||||||
|
test: /\.purs$/,
|
||||||
|
loader: 'purs-loader',
|
||||||
|
exclude: /node_modules/,
|
||||||
|
query: {
|
||||||
|
psc: 'psa',
|
||||||
|
bundle: true,
|
||||||
|
warnings: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
'process.env.NODE_ENV': JSON.stringify('production')
|
||||||
|
}),
|
||||||
|
new webpack.optimize.OccurrenceOrderPlugin(true),
|
||||||
|
new webpack.LoaderOptionsPlugin({
|
||||||
|
minimize: true,
|
||||||
|
debug: false
|
||||||
|
}),
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
template: 'support/index.html',
|
||||||
|
inject: 'body',
|
||||||
|
filename: 'index.html'
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
resolveLoader: {
|
||||||
|
modules: [
|
||||||
|
path.join(__dirname, 'node_modules')
|
||||||
|
]
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
modules: [
|
||||||
|
'node_modules',
|
||||||
|
'bower_components'
|
||||||
|
],
|
||||||
|
extensions: ['.js', '.purs']
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue