├── .gitignore
├── src
├── static
│ ├── img
│ │ ├── elm.jpg
│ │ ├── favicon.ico
│ │ └── elm-bootstrap.svg
│ ├── index.js
│ ├── index.html
│ └── bootstrap.scss
└── elm
│ ├── Components
│ └── Hello.elm
│ ├── Stylesheets.elm
│ ├── MainCss.elm
│ ├── HomePage.elm
│ ├── Main.elm
│ ├── RouteHelper.elm
│ ├── Router.elm
│ └── Navbar.elm
├── postcss.config.js
├── elm-package.json
├── package.json
├── README.md
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | elm-stuff/
2 | node_modules/
3 | tmp/
4 | dist/
5 |
--------------------------------------------------------------------------------
/src/static/img/elm.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiwhiz/elm-bootstrap-webpack-starter/HEAD/src/static/img/elm.jpg
--------------------------------------------------------------------------------
/src/static/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jiwhiz/elm-bootstrap-webpack-starter/HEAD/src/static/img/favicon.ico
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require('autoprefixer')( { browsers: ['last 2 versions'] } )
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/src/static/index.js:
--------------------------------------------------------------------------------
1 | // pull in desired CSS/SASS files
2 | require('./bootstrap')
3 | require('../elm/Stylesheets')
4 |
5 | // inject bundled Elm app into div#main
6 | var Elm = require( '../elm/Main' );
7 | Elm.Main.embed( document.getElementById( 'main' ) );
8 |
--------------------------------------------------------------------------------
/src/elm/Components/Hello.elm:
--------------------------------------------------------------------------------
1 | module Components.Hello exposing (..)
2 |
3 | import Html exposing (..)
4 | import Html.Attributes exposing (..)
5 | import String
6 |
7 |
8 | -- hello component
9 |
10 |
11 | hello : Int -> Html a
12 | hello model =
13 | div
14 | [ class "h1" ]
15 | [ text ("Hello, Elm" ++ ("!" |> String.repeat model)) ]
16 |
--------------------------------------------------------------------------------
/src/elm/Stylesheets.elm:
--------------------------------------------------------------------------------
1 | port module Stylesheets exposing (..)
2 |
3 | import Css.File exposing (..)
4 | import MainCss as Main
5 |
6 |
7 | port files : CssFileStructure -> Cmd msg
8 |
9 |
10 | cssFiles : CssFileStructure
11 | cssFiles =
12 | toFileStructure [ ( "main.css", compile [ Main.css ] ) ]
13 |
14 |
15 | main : CssCompilerProgram
16 | main =
17 | Css.File.compiler files cssFiles
18 |
--------------------------------------------------------------------------------
/src/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | elm-webpack-starter
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/static/bootstrap.scss:
--------------------------------------------------------------------------------
1 |
2 | // Bootstrap overrides
3 | //
4 | // Copy variables from `_variables.scss` to this file to override default values
5 | // without modifying source files.
6 |
7 | // Reassign color vars to semantic color scheme
8 | $brand-primary: rgb(86,63,122);
9 |
10 | $navbar-light-color: rgba($brand-primary,.75);
11 | $navbar-light-hover-color: rgba($brand-primary,1.25);
12 | $navbar-light-active-color: rgba($brand-primary,1);
13 |
14 | @import '~bootstrap/scss/bootstrap.scss';
15 |
16 | $fa-font-path: "~font-awesome/fonts";
17 | @import '~font-awesome/scss/font-awesome.scss';
18 |
--------------------------------------------------------------------------------
/src/elm/MainCss.elm:
--------------------------------------------------------------------------------
1 | module MainCss exposing (..)
2 |
3 | import Html exposing (Attribute)
4 | import Html.Attributes
5 | import Css exposing (..)
6 | import Css.Elements exposing (body)
7 | import Css.Namespace exposing (namespace)
8 |
9 |
10 | type CssClasses
11 | = NavBar
12 | | Jumbotron
13 | | BrandLogo
14 |
15 |
16 | type CssIds
17 | = Page
18 |
19 |
20 | css : Stylesheet
21 | css =
22 | (stylesheet << namespace "ebws")
23 | [ body
24 | [ minHeight (Css.rem 75)
25 | , paddingTop (Css.rem 4.5)
26 | ]
27 | , class Jumbotron
28 | [ textAlign center
29 | ]
30 | , class BrandLogo
31 | [ width (px 30)
32 | ]
33 | ]
34 |
35 |
36 | styles : List Css.Mixin -> Attribute msg
37 | styles =
38 | Css.asPairs >> Html.Attributes.style
39 |
--------------------------------------------------------------------------------
/elm-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.1.0",
3 | "summary": "Example using `elm-webpack-loader`.",
4 | "repository": "https://github.com/jiwhiz/elm-bootstrap-webpack-starter.git",
5 | "license": "MIT",
6 | "source-directories": [
7 | "src/elm"
8 | ],
9 | "exposed-modules": [],
10 | "dependencies": {
11 | "elm-lang/core": "5.0.0 <= v < 6.0.0",
12 | "elm-lang/html": "2.0.0 <= v < 3.0.0",
13 | "elm-lang/http": "1.0.0 <= v < 2.0.0",
14 | "elm-lang/navigation": "2.1.0 <= v < 3.0.0",
15 | "evancz/elm-markdown": "3.0.1 <= v < 4.0.0",
16 | "evancz/url-parser": "2.0.1 <= v < 3.0.0",
17 | "Fresheyeball/elm-font-awesome": "2.0.2 <= v < 3.0.0",
18 | "rtfeldman/elm-css": "8.1.0 <= v < 9.0.0",
19 | "rtfeldman/elm-css-helpers": "2.0.1 <= v < 3.0.0",
20 | "rundis/elm-bootstrap": "2.0.0 <= v < 3.0.0"
21 | },
22 | "elm-version": "0.18.0 <= v < 0.19.0"
23 | }
24 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "elm-bootstrap-webpack-starter",
3 | "description": "Webpack setup for writing Elm apps with elm-bootstrap",
4 | "version": "0.1.0",
5 | "license": "MIT",
6 | "author": "Yuan Ji",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/jiwhiz/elm-bootstrap-webpack-starter"
10 | },
11 | "scripts": {
12 | "start": "webpack-dev-server --hot --inline",
13 | "build": "rimraf dist && webpack ",
14 | "reinstall": "npm i rimraf && rimraf elm-stuff && rimraf node_modules && npm i && elm package install",
15 | "local": "http-server dist"
16 | },
17 | "devDependencies": {
18 | "autoprefixer": "^6.3.6",
19 | "bootstrap": "4.0.0-alpha.6",
20 | "copy-webpack-plugin": "^4.0.1",
21 | "css-loader": "^0.27.2",
22 | "elm": "^0.18.0",
23 | "elm-css-webpack-loader": "^3.1.0",
24 | "elm-hot-loader": "^0.5.4",
25 | "elm-webpack-loader": "^4.2.0",
26 | "extract-text-webpack-plugin": "^2.1.0",
27 | "file-loader": "^0.10.1",
28 | "font-awesome": "^4.7.0",
29 | "html-webpack-plugin": "^2.28.0",
30 | "http-server": "^0.9.0",
31 | "node-sass": "^4.2.0",
32 | "postcss-loader": "^1.1.1",
33 | "rimraf": "^2.5.2",
34 | "sass-loader": "^6.0.0",
35 | "style-loader": "^0.13.1",
36 | "url-loader": "^0.5.7",
37 | "webpack": "^2.2.1",
38 | "webpack-dev-server": "^2.4.1",
39 | "webpack-merge": "^3.0.0"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/elm/HomePage.elm:
--------------------------------------------------------------------------------
1 | module HomePage exposing (..)
2 |
3 | import Html exposing (..)
4 | import Html.Attributes exposing (..)
5 | import Html.Events exposing (onClick)
6 | import Bootstrap.Button as Button
7 | import Css
8 | import Html.CssHelpers
9 | import MainCss
10 | import Components.Hello exposing (hello)
11 |
12 |
13 | type Msg
14 | = Increment
15 |
16 |
17 | type alias Model =
18 | { count : Int
19 | }
20 |
21 |
22 | { id, class, classList } =
23 | Html.CssHelpers.withNamespace "ebws"
24 |
25 |
26 | init : Model
27 | init =
28 | { count = 0
29 | }
30 |
31 |
32 | update : Msg -> Model -> ( Model, Cmd Msg )
33 | update msg model =
34 | ( { count = model.count + 1 }, Cmd.none )
35 |
36 |
37 | view : Model -> Html Msg
38 | view model =
39 | div [ class [ MainCss.Jumbotron ] ]
40 | [ img
41 | [ src "static/img/elm.jpg"
42 | , MainCss.styles
43 | [ Css.width (Css.pct 33)
44 | , Css.border3 (Css.px 4) Css.solid (Css.hex "#337AB7")
45 | ]
46 | ]
47 | []
48 | , hello model.count
49 | , p [] [ text ("Elm Bootstrap Webpack Starter") ]
50 | , Button.button
51 | [ Button.primary
52 | , Button.large
53 | , Button.attrs [ onClick Increment ]
54 | ]
55 | [ span [] []
56 | , span [] [ text "FTW!" ]
57 | ]
58 | ]
59 |
--------------------------------------------------------------------------------
/src/static/img/elm-bootstrap.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # elm-bootstrap-webpack-starter
2 |
3 |
4 | ### About:
5 | A simple Webpack 2 setup for writing [Elm](http://elm-lang.org/) apps
6 | with [elm-bootstrap](http://elm-bootstrap.info/):
7 |
8 | * Dev server with live reloading, HMR
9 | * Support for CSS/SCSS (with Autoprefixer), image assets
10 | * Bundling and minification for deployment
11 | * Bootstrap 4 Template
12 | [fixed navbar example](https://v4-alpha.getbootstrap.com/examples/navbar-top-fixed)
13 | implemented by [elm-bootstrap Navbar](http://elm-bootstrap.info/navbar)
14 | * Use [elm-css](https://github.com/rtfeldman/elm-css) to generate css from elm code
15 | * Use [elm-css-webpack-loader](https://github.com/jiwhiz/elm-css-webpack-loader/tree/upgrade)
16 | to load Stylesheets.elm as css
17 |
18 |
19 | ### Install:
20 | Clone this repo into a new project folder, e.g. `my-elm-project`:
21 | ```
22 | git clone https://github.com/jiwhiz/elm-bootstrap-webpack-starter my-elm-project
23 | cd my-elm-project
24 | ```
25 |
26 | Re-initialize the project folder as your own repo:
27 | ```
28 | rm -rf .git # on Windows: rmdir .git /s /q
29 | git init
30 | git add .
31 | git commit -m 'first commit'
32 | ```
33 |
34 | Install all dependencies using the handy `reinstall` script:
35 | ```
36 | npm run reinstall
37 | ```
38 | *This does a clean (re)install of all npm and elm packages.*
39 |
40 |
41 | ### Serve locally:
42 | ```
43 | npm start
44 | ```
45 | * Access app at `http://localhost:8080/`
46 | * Get coding! The entry point file is `src/elm/Main.elm`
47 | * Browser will refresh automatically on any file changes..
48 |
49 |
50 | ### Build & bundle for prod:
51 | ```
52 | npm run build
53 | ```
54 |
55 | * Files are saved into the `/dist` folder
56 | * To run locally, use `npm run local`
57 |
58 |
59 | ### Credits:
60 |
61 | * [elm-community/elm-webpack-starter](https://github.com/elm-community/elm-webpack-starter)
62 | * [rundis/albums](https://github.com/rundis/albums)
63 | * [ohanhi/elm-taco](https://github.com/ohanhi/elm-taco)
64 |
--------------------------------------------------------------------------------
/src/elm/Main.elm:
--------------------------------------------------------------------------------
1 | module Main exposing (..)
2 |
3 | import Html exposing (..)
4 | import Html.CssHelpers
5 | import Navigation exposing (Location)
6 | import Bootstrap.Navbar
7 | import Router
8 |
9 |
10 | { id, class, classList } =
11 | Html.CssHelpers.withNamespace "ebws"
12 |
13 |
14 | type Msg
15 | = OnLocationChange Location
16 | | RouterMsg Router.Msg
17 |
18 |
19 | type alias Model =
20 | { routerModel : Router.Model
21 | }
22 |
23 |
24 | main : Program Never Model Msg
25 | main =
26 | Navigation.program OnLocationChange
27 | { init = init
28 | , view = view
29 | , update = update
30 | , subscriptions = subscriptions
31 | }
32 |
33 |
34 | init : Navigation.Location -> ( Model, Cmd Msg )
35 | init location =
36 | let
37 | ( routerModel, routerCmd ) =
38 | Router.init location
39 | in
40 | ( { routerModel = routerModel
41 | }
42 | , routerCmd |> Cmd.map RouterMsg
43 | )
44 |
45 |
46 | subscriptions : Model -> Sub Msg
47 | subscriptions model =
48 | Bootstrap.Navbar.subscriptions model.routerModel.navbarState Router.NavbarMsg |> Sub.map RouterMsg
49 |
50 |
51 | update : Msg -> Model -> ( Model, Cmd Msg )
52 | update msg model =
53 | case msg of
54 | OnLocationChange location ->
55 | let
56 | ( routerModel, routerCmd ) =
57 | Router.update (Router.OnLocationChange location) model.routerModel
58 | in
59 | ( { model | routerModel = routerModel }, routerCmd |> Cmd.map RouterMsg )
60 |
61 | RouterMsg routerMsg ->
62 | let
63 | ( routerModel, routerCmd ) =
64 | Router.update routerMsg model.routerModel
65 | in
66 | ( { model | routerModel = routerModel }, routerCmd |> Cmd.map RouterMsg )
67 |
68 |
69 | view : Model -> Html Msg
70 | view model =
71 | div []
72 | [ Router.view model.routerModel |> Html.map RouterMsg
73 | ]
74 |
--------------------------------------------------------------------------------
/src/elm/RouteHelper.elm:
--------------------------------------------------------------------------------
1 | module RouteHelper exposing (..)
2 |
3 | import Html exposing (..)
4 | import Html.Attributes exposing (..)
5 | import Html.Events exposing (onClick)
6 | import UrlParser exposing (Parser, (>), int, oneOf, s)
7 | import Navigation exposing (Location)
8 | import Html.Attributes exposing (href, attribute)
9 | import Html exposing (Html, Attribute, a)
10 | import Html.Events exposing (onWithOptions)
11 | import Bootstrap.Navbar
12 | import Json.Decode as Json
13 |
14 |
15 | type Route
16 | = HomeRoute
17 | | AboutRoute
18 | | NotFoundRoute
19 |
20 |
21 | routeParser : Parser (Route -> a) a
22 | routeParser =
23 | UrlParser.oneOf
24 | [ UrlParser.map HomeRoute (UrlParser.s "")
25 | , UrlParser.map AboutRoute (UrlParser.s "about")
26 | ]
27 |
28 |
29 | parseLocation : Navigation.Location -> Route
30 | parseLocation location =
31 | case (UrlParser.parsePath routeParser location) of
32 | Just route ->
33 | route
34 |
35 | Nothing ->
36 | NotFoundRoute
37 |
38 |
39 | encode : Route -> String
40 | encode route =
41 | case route of
42 | HomeRoute ->
43 | "/"
44 |
45 | AboutRoute ->
46 | "/about"
47 |
48 | NotFoundRoute ->
49 | "/"
50 |
51 |
52 | navigate : Route -> Cmd msg
53 | navigate route =
54 | Navigation.newUrl (encode route)
55 |
56 |
57 | linkTo : Route -> List (Attribute msg) -> List (Html msg) -> Html msg
58 | linkTo route attrs content =
59 | a ((linkAttrs route) ++ attrs) content
60 |
61 |
62 | linkAttrs : Route -> List (Attribute msg)
63 | linkAttrs route =
64 | let
65 | path =
66 | encode route
67 | in
68 | [ href path
69 | , attribute "data-navigate" path
70 | ]
71 |
72 |
73 | catchNavigationClicks : msg -> Attribute msg
74 | catchNavigationClicks message =
75 | onWithOptions "click"
76 | { stopPropagation = True
77 | , preventDefault = True
78 | }
79 | (Json.succeed message)
80 |
81 |
82 | pathDecoder : Json.Decoder String
83 | pathDecoder =
84 | Json.oneOf
85 | [ Json.at [ "data-navigate" ] Json.string
86 | , Json.at [ "parentElement" ] (Json.lazy (\_ -> pathDecoder))
87 | , Json.fail "no path found for click"
88 | ]
89 |
--------------------------------------------------------------------------------
/src/elm/Router.elm:
--------------------------------------------------------------------------------
1 | module Router exposing (..)
2 |
3 | import Html exposing (..)
4 | import Navigation exposing (Location)
5 | import Html exposing (Html, Attribute, a)
6 | import Bootstrap.Grid as Grid
7 | import Bootstrap.Navbar
8 | import HomePage
9 | import Navbar
10 | import RouteHelper exposing (..)
11 |
12 |
13 | type Msg
14 | = ChangeLocation String
15 | | OnLocationChange Location
16 | | NavbarMsg Bootstrap.Navbar.State
17 | | HomePageMsg HomePage.Msg
18 |
19 |
20 | type alias Model =
21 | { route : Route
22 | , navbarState : Bootstrap.Navbar.State
23 | , homePageModel : HomePage.Model
24 | }
25 |
26 |
27 | init : Navigation.Location -> ( Model, Cmd Msg )
28 | init location =
29 | let
30 | currentRoute =
31 | parseLocation location
32 |
33 | ( navbarState, navbarCmd ) =
34 | Bootstrap.Navbar.initialState NavbarMsg
35 | in
36 | ( { route = currentRoute
37 | , navbarState = navbarState
38 | , homePageModel = HomePage.init
39 | }
40 | , navbarCmd
41 | )
42 |
43 |
44 | update : Msg -> Model -> ( Model, Cmd Msg )
45 | update msg model =
46 | case msg of
47 | ChangeLocation path ->
48 | ( model, Navigation.newUrl path )
49 |
50 | OnLocationChange location ->
51 | let
52 | newRoute =
53 | parseLocation location
54 | in
55 | ( { model | route = newRoute }, Cmd.none )
56 |
57 | NavbarMsg state ->
58 | ( { model | navbarState = state }, Cmd.none )
59 |
60 | HomePageMsg homePageMsg ->
61 | updateHomePage homePageMsg model
62 |
63 |
64 | updateHomePage : HomePage.Msg -> Model -> ( Model, Cmd Msg )
65 | updateHomePage msg model =
66 | let
67 | ( homePageModel, homePageCmd ) =
68 | HomePage.update msg model.homePageModel
69 | in
70 | ( { model | homePageModel = homePageModel }, homePageCmd |> Cmd.map HomePageMsg )
71 |
72 |
73 | view : Model -> Html Msg
74 | view model =
75 | div []
76 | [ Navbar.view model.navbarState model.route ChangeLocation NavbarMsg
77 | , page model
78 | ]
79 |
80 |
81 | page : Model -> Html Msg
82 | page model =
83 | Grid.container []
84 | [ case model.route of
85 | HomeRoute ->
86 | Html.map HomePageMsg (HomePage.view model.homePageModel)
87 |
88 | AboutRoute ->
89 | text "About"
90 |
91 | NotFoundRoute ->
92 | text "Not Found"
93 | ]
94 |
--------------------------------------------------------------------------------
/src/elm/Navbar.elm:
--------------------------------------------------------------------------------
1 | module Navbar exposing (..)
2 |
3 | import Html exposing (..)
4 | import Html.Attributes exposing (..)
5 | import Html.CssHelpers
6 | import Bootstrap.Button as Button
7 | import Bootstrap.Form.Input as Input
8 | import Bootstrap.Navbar as Navbar exposing (State)
9 | import FontAwesome.Web as Icon
10 | import MainCss
11 | import RouteHelper exposing (..)
12 |
13 |
14 | { id, class, classList } =
15 | Html.CssHelpers.withNamespace "ebws"
16 |
17 |
18 | view : State -> Route -> (String -> msg) -> (State -> msg) -> Html msg
19 | view state currentRoute changeLocationMsgTagger navbarMsgTagger =
20 | div []
21 | [ Navbar.config navbarMsgTagger
22 | |> Navbar.withAnimation
23 | |> Navbar.collapseMedium
24 | |> Navbar.fixTop
25 | |> Navbar.brand
26 | [ href "/" ]
27 | [ img
28 | [ src "static/img/elm-bootstrap.svg"
29 | , class [ MainCss.BrandLogo ]
30 | ]
31 | []
32 | , text " Project"
33 | ]
34 | |> Navbar.items
35 | [ routeToItemLink changeLocationMsgTagger currentRoute HomeRoute Icon.home " Home"
36 | , routeToItemLink changeLocationMsgTagger currentRoute AboutRoute Icon.info " About"
37 | , Navbar.dropdown
38 | { id = "mydropdown"
39 | , toggle = Navbar.dropdownToggle [] [ text "My dropdown" ]
40 | , items =
41 | [ Navbar.dropdownHeader [ text "Heading" ]
42 | , routeToDropdownItem changeLocationMsgTagger HomeRoute "Drop Item 1"
43 | , routeToDropdownItem changeLocationMsgTagger HomeRoute "Drop Item 2"
44 | , Navbar.dropdownDivider
45 | , routeToDropdownItem changeLocationMsgTagger HomeRoute "Drop Item 3"
46 | ]
47 | }
48 | ]
49 | |> Navbar.customItems
50 | [ Navbar.formItem []
51 | [ Input.text [ Input.attrs <| [ placeholder "enter" ] ]
52 | , Button.button
53 | [ Button.outlineSuccess
54 | , Button.attrs [ Html.Attributes.class "ml-sm-2" ]
55 | ]
56 | [ text "Search" ]
57 | ]
58 | , Navbar.textItem [ Html.Attributes.class "muted ml-sm-2" ] [ text "Text" ]
59 | ]
60 | |> Navbar.view state
61 | ]
62 |
63 |
64 | routeToItemLink : (String -> msg) -> Route -> Route -> Html msg -> String -> Navbar.Item msg
65 | routeToItemLink changeLocationMsgTagger currentRoute linkedToRoute icon title =
66 | let
67 | path =
68 | encode linkedToRoute
69 |
70 | itemLink =
71 | if currentRoute == linkedToRoute then
72 | Navbar.itemLinkActive
73 | else
74 | Navbar.itemLink
75 | in
76 | itemLink
77 | [ href path
78 | , attribute "data-navigate" path
79 | , catchNavigationClicks (changeLocationMsgTagger path)
80 | ]
81 | [ icon, text title ]
82 |
83 |
84 | routeToDropdownItem : (String -> msg) -> Route -> String -> Navbar.DropdownItem msg
85 | routeToDropdownItem changeLocationMsgTagger linkedToRoute title =
86 | let
87 | path =
88 | encode linkedToRoute
89 | in
90 | Navbar.dropdownItem
91 | [ href path
92 | , attribute "data-navigate" path
93 | , catchNavigationClicks (changeLocationMsgTagger path)
94 | ]
95 | [ text title ]
96 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require( 'path' );
2 | var webpack = require( 'webpack' );
3 | var merge = require( 'webpack-merge' );
4 | var HtmlWebpackPlugin = require( 'html-webpack-plugin' );
5 | var autoprefixer = require( 'autoprefixer' );
6 | var ExtractTextPlugin = require( 'extract-text-webpack-plugin' );
7 | var CopyWebpackPlugin = require( 'copy-webpack-plugin' );
8 | var entryPath = path.join( __dirname, 'src/static/index.js' );
9 | var outputPath = path.join( __dirname, 'dist' );
10 |
11 | console.log( 'WEBPACK GO!');
12 |
13 | // determine build env
14 | var TARGET_ENV = process.env.npm_lifecycle_event === 'build' ? 'production' : 'development';
15 | var outputFilename = TARGET_ENV === 'production' ? '[name]-[hash].js' : '[name].js'
16 |
17 | // common webpack config
18 | var commonConfig = {
19 |
20 | output: {
21 | path: outputPath,
22 | filename: `static/js/${outputFilename}`,
23 | publicPath: '/'
24 | },
25 |
26 | resolve: {
27 | extensions: ['.js', '.elm', '.scss']
28 | },
29 |
30 | module: {
31 | rules: [
32 | {
33 | test: /\.(eot|ttf|svg)$/,
34 | loader: 'file-loader'
35 | }
36 | ]
37 | },
38 |
39 | plugins: [
40 | new HtmlWebpackPlugin({
41 | template: 'src/static/index.html',
42 | inject: 'body',
43 | filename: 'index.html'
44 | })
45 | ]
46 |
47 | }
48 |
49 | // additional webpack settings for local env (when invoked by 'npm start')
50 | if ( TARGET_ENV === 'development' ) {
51 | console.log( 'Serving locally...');
52 |
53 | module.exports = merge( commonConfig, {
54 |
55 | entry: [
56 | 'webpack-dev-server/client?http://localhost:8080',
57 | entryPath
58 | ],
59 |
60 | devServer: {
61 | // serve index.html in place of 404 responses
62 | historyApiFallback: true,
63 | contentBase: './src',
64 | },
65 |
66 | module: {
67 | rules: [
68 | {
69 | test: /\.elm$/,
70 | exclude: [/elm-stuff/, /node_modules/, /Stylesheets\.elm$/],
71 | use: [
72 | 'elm-hot-loader',
73 | 'elm-webpack-loader'
74 | ]
75 | },
76 | {
77 | test: /Stylesheets\.elm$/,
78 | use: [
79 | 'style-loader',
80 | 'css-loader',
81 | 'elm-css-webpack-loader'
82 | ]
83 | },
84 | {
85 | test: /\.scss$/,
86 | use: [
87 | 'style-loader',
88 | 'css-loader',
89 | 'postcss-loader',
90 | 'sass-loader'
91 | ]
92 | },
93 | {
94 | test: /\.(woff|woff2)(\?v=[a-z0-9]\.[a-z0-9]\.[a-z0-9])?$/,
95 | loader: 'url-loader?limit=100000'
96 | }
97 | ]
98 | }
99 |
100 | });
101 | }
102 |
103 | // additional webpack settings for prod env (when invoked via 'npm run build')
104 | if ( TARGET_ENV === 'production' ) {
105 | console.log( 'Building for prod...');
106 |
107 | module.exports = merge( commonConfig, {
108 |
109 | entry: entryPath,
110 |
111 | module: {
112 | rules: [
113 | {
114 | test: /\.elm$/,
115 | exclude: [/elm-stuff/, /node_modules/, /Stylesheets\.elm/],
116 | use: 'elm-webpack-loader'
117 | },
118 | {
119 | test: /Stylesheets\.elm$/,
120 | use: ExtractTextPlugin.extract({
121 | fallback: "style-loader",
122 | use: [
123 | 'css-loader',
124 | 'elm-css-webpack-loader'
125 | ]
126 | })
127 | },
128 | {
129 | test: /\.scss$/,
130 | use: ExtractTextPlugin.extract({
131 | fallback: 'style-loader',
132 | use: [
133 | 'css-loader',
134 | 'postcss-loader',
135 | 'sass-loader'
136 | ]
137 | })
138 | },
139 | {
140 | test: /\.(woff|woff2)(\?v=[a-z0-9]\.[a-z0-9]\.[a-z0-9])?$/,
141 | loader: 'url-loader?limit=100000'
142 | }
143 | ]
144 | },
145 |
146 | plugins: [
147 | new CopyWebpackPlugin([
148 | {
149 | from: 'src/static/img/',
150 | to: 'static/img/'
151 | }
152 | ]),
153 |
154 | new webpack.optimize.OccurrenceOrderPlugin(),
155 |
156 | // extract CSS into a separate file
157 | new ExtractTextPlugin( 'static/styles/[name]-[hash].css'),
158 |
159 | // minify & mangle JS/CSS
160 | new webpack.optimize.UglifyJsPlugin({
161 | minimize: true,
162 | compressor: { warnings: false }
163 | // mangle: true
164 | })
165 | ],
166 |
167 | });
168 | }
169 |
--------------------------------------------------------------------------------