├── .gitignore
├── src
├── favicon.ico
├── static
│ ├── img
│ │ └── elm.jpg
│ ├── styles
│ │ └── main.scss
│ ├── index.js
│ └── index.html
└── elm
│ ├── Components
│ └── Hello.elm
│ └── Main.elm
├── elm-package.json
├── package.json
├── README.md
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | elm-stuff/
2 | node_modules/
3 | tmp/
4 | dist/
5 | yarn.lock
6 |
7 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elm-community/elm-webpack-starter/master/src/favicon.ico
--------------------------------------------------------------------------------
/src/static/img/elm.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elm-community/elm-webpack-starter/master/src/static/img/elm.jpg
--------------------------------------------------------------------------------
/src/static/styles/main.scss:
--------------------------------------------------------------------------------
1 | $icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/';
2 | @import '~bootstrap-sass/assets/stylesheets/bootstrap/_mixins.scss';
3 | @import '~bootstrap-sass/assets/stylesheets/_bootstrap.scss';
4 |
5 | // can add Boostrap overrides, additional Sass/CSS below...
6 |
--------------------------------------------------------------------------------
/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 | -- hello component
8 | hello : Int -> Html a
9 | hello model =
10 | div
11 | [ class "h1" ]
12 | [ text ( "Hello, Elm" ++ ( "!" |> String.repeat model ) ) ]
13 |
--------------------------------------------------------------------------------
/src/static/index.js:
--------------------------------------------------------------------------------
1 | // pull in desired CSS/SASS files
2 | require( './styles/main.scss' );
3 | var $ = jQuery = require( '../../node_modules/jquery/dist/jquery.js' ); // <--- remove if jQuery not needed
4 | require( '../../node_modules/bootstrap-sass/assets/javascripts/bootstrap.js' ); // <--- remove if Bootstrap's JS not needed
5 |
6 | // inject bundled Elm app into div#main
7 | var Elm = require( '../elm/Main' );
8 | Elm.Main.embed( document.getElementById( 'main' ) );
9 |
--------------------------------------------------------------------------------
/src/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | elm-webpack-starter
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/elm-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0.0",
3 | "summary": "Example using `elm-webpack-loader`.",
4 | "repository": "https://github.com/moarwick/elm-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 | "evancz/elm-markdown": "3.0.1 <= v < 4.0.0"
15 | },
16 | "elm-version": "0.18.0 <= v < 0.19.0"
17 | }
18 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "elm-webpack-starter",
3 | "description": "Webpack setup for writing Elm apps",
4 | "version": "0.8.6",
5 | "license": "MIT",
6 | "author": "Peter Morawiec",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/moarwick/elm-webpack-starter"
10 | },
11 | "scripts": {
12 | "start": "webpack-dev-server --hot --inline",
13 | "prebuild": "rimraf dist",
14 | "build": "webpack",
15 | "reinstall": "npm i rimraf && rimraf node_modules && npm uninstall -g elm && npm i -g elm && npm i && elm package install"
16 | },
17 | "devDependencies": {
18 | "autoprefixer": "^6.7.7",
19 | "bootstrap-sass": "^3.3.7",
20 | "copy-webpack-plugin": "^4.0.1",
21 | "css-loader": "^0.27.3",
22 | "elm": "^0.18.0",
23 | "elm-webpack-loader": "^4.3.0",
24 | "extract-text-webpack-plugin": "^2.1.0",
25 | "file-loader": "^0.10.1",
26 | "html-webpack-plugin": "^2.28.0",
27 | "jquery": "^3.2.1",
28 | "node-sass": "^4.5.1",
29 | "postcss-loader": "^1.3.3",
30 | "rimraf": "^2.6.1",
31 | "sass-loader": "^6.0.3",
32 | "style-loader": "^0.16.0",
33 | "url-loader": "^0.5.8",
34 | "webpack": "^2.3.1",
35 | "webpack-dev-server": "^2.4.2",
36 | "webpack-merge": "^4.1.0"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/elm/Main.elm:
--------------------------------------------------------------------------------
1 | module Main exposing (..)
2 | import Html exposing (..)
3 | import Html.Attributes exposing (..)
4 | import Html.Events exposing ( onClick )
5 |
6 | -- component import example
7 | import Components.Hello exposing ( hello )
8 |
9 |
10 | -- APP
11 | main : Program Never Model Msg
12 | main =
13 | Html.beginnerProgram { model = model, view = view, update = update }
14 |
15 |
16 | -- MODEL
17 | type alias Model = Int
18 |
19 | model : Model
20 | model = 0
21 |
22 |
23 | -- UPDATE
24 | type Msg = NoOp | Increment
25 |
26 | update : Msg -> Model -> Model
27 | update msg model =
28 | case msg of
29 | NoOp -> model
30 | Increment -> model + 1
31 |
32 |
33 | -- VIEW
34 | -- Html is defined as: elem [ attribs ][ children ]
35 | -- CSS can be applied via class names or inline style attrib
36 | view : Model -> Html Msg
37 | view model =
38 | div [ class "container", style [("margin-top", "30px"), ( "text-align", "center" )] ][ -- inline CSS (literal)
39 | div [ class "row" ][
40 | div [ class "col-xs-12" ][
41 | div [ class "jumbotron" ][
42 | img [ src "static/img/elm.jpg", style styles.img ] [] -- inline CSS (via var)
43 | , hello model -- ext 'hello' component (takes 'model' as arg)
44 | , p [] [ text ( "Elm Webpack Starter" ) ]
45 | , button [ class "btn btn-primary btn-lg", onClick Increment ] [ -- click handler
46 | span[ class "glyphicon glyphicon-star" ][] -- glyphicon
47 | , span[][ text "FTW!" ]
48 | ]
49 | ]
50 | ]
51 | ]
52 | ]
53 |
54 |
55 | -- CSS STYLES
56 | styles : { img : List ( String, String ) }
57 | styles =
58 | {
59 | img =
60 | [ ( "width", "33%" )
61 | , ( "border", "4px solid #337AB7")
62 | ]
63 | }
64 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # elm-webpack-starter
2 |
3 |
4 | ### About:
5 | A simple Webpack setup for writing [Elm](http://elm-lang.org/) apps:
6 |
7 | * Dev server with live reloading, HMR
8 | * Support for CSS/SCSS (with Autoprefixer), image assets
9 | * Bootstrap 3.3+ (Sass version)
10 | * Bundling and minification for deployment
11 | * Basic app scaffold, using `Html.beginnerProgram`
12 | * A snippet of example code to get you started!
13 |
14 |
15 | ### Install:
16 | Clone this repo into a new project folder, e.g. `my-elm-project`:
17 | ```
18 | git clone https://github.com/moarwick/elm-webpack-starter my-elm-project
19 | cd my-elm-project
20 | ```
21 |
22 | Re-initialize the project folder as your own repo:
23 | ```
24 | rm -rf .git # on Windows: rmdir .git /s /q
25 | git init
26 | git add .
27 | git commit -m 'first commit'
28 | ```
29 |
30 | Install all dependencies using the handy `reinstall` script:
31 | ```
32 | npm run reinstall
33 | ```
34 | *This does a clean (re)install of all npm and elm packages, plus a global elm install.*
35 |
36 |
37 | ### Serve locally:
38 | ```
39 | npm start
40 | ```
41 | * Access app at `http://localhost:8080/`
42 | * Get coding! The entry point file is `src/elm/Main.elm`
43 | * Browser will refresh automatically on any file changes..
44 |
45 |
46 | ### Build & bundle for prod:
47 | ```
48 | npm run build
49 | ```
50 |
51 | * Files are saved into the `/dist` folder
52 | * To check it, open `dist/index.html`
53 |
54 |
55 | ### Changelog
56 |
57 | **Ver 0.8.6**
58 | * Update Packages (-> Webpack 2)
59 | * fix paths in file-loader
60 | * clean up build script
61 |
62 | **Ver 0.8.5**
63 | * Fix loading path of generated js file, per [Issue 47](https://github.com/moarwick/elm-webpack-starter/issues/47)
64 |
65 | **Ver 0.8.4**
66 | * Fix hot reloading of components, per [Issue 44](https://github.com/moarwick/elm-webpack-starter/issues/44)
67 |
68 | **Ver 0.8.3**
69 | * Update packages
70 | * Attempt to fix path issues when building for prod (temp)
71 |
72 | **Ver 0.8.2**
73 | * Webpack config improvements (PR by [Lesuk](https://github.com/moarwick/elm-webpack-starter/pull/39))
74 |
75 | **Ver 0.8.0**
76 | * Update to Elm 0.18, use `debug=true` on webpack loader (PR by [douglascorrea](https://github.com/moarwick/elm-webpack-starter/pull/33))
77 | * Add a script for one-step installs
78 | * Update to latest packages
79 |
80 | **Ver 0.7.1**
81 | * Fix favicon issues, per [Issue 30](https://github.com/moarwick/elm-webpack-starter/issues/30)
82 |
83 | **Ver 0.7.0**
84 | * Modify project structure, per [Issue 26](https://github.com/moarwick/elm-webpack-starter/issues/26)
85 | * Include Bootstrap JS, per [Issue 28](https://github.com/moarwick/elm-webpack-starter/issues/28)
86 | * More helpful install steps in README, per [Issue 29](https://github.com/moarwick/elm-webpack-starter/issues/29)
87 | * Update to latest packages
88 |
89 | **Ver 0.6.2**
90 | * Use `copy-webpack-plugin` instead of `cp` to copy files (Windows compatible)
91 |
92 | **Ver 0.6.0**
93 | * `elm-hot-loader` is back (no Elm code changes required!)
94 | * Switch to [bootstrap-sass](https://www.npmjs.com/package/bootstrap-sass) to demo CSS
95 |
96 | **Ver 0.5.0**
97 | * Update to Elm 0.17.0 (and other latest modules)
98 | * Upgrade starter code per [upgrade-docs](https://github.com/elm-lang/elm-platform/blob/master/upgrade-docs/0.17.md)
99 | * Remove `elm-hot-loader` (for now)
100 |
101 | **Ver 0.4.0**
102 | * Add [elm-hot-loader](https://github.com/fluxxu/elm-hot-loader) for HMR support (PR by [fluxxu](https://github.com/fluxxu))
103 |
104 | **Ver 0.3.0**
105 | * Use `html-webpack-plugin` to generate `index.html`
106 | * Apply hash filenames for bundled JS and CSS (prevents caching)
107 | * Image and favicon assets copied to `dist/`
108 |
--------------------------------------------------------------------------------
/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 |
9 |
10 | const prod = 'production';
11 | const dev = 'development';
12 |
13 | // determine build env
14 | const TARGET_ENV = process.env.npm_lifecycle_event === 'build' ? prod : dev;
15 | const isDev = TARGET_ENV == dev;
16 | const isProd = TARGET_ENV == prod;
17 |
18 | // entry and output path/filename variables
19 | const entryPath = path.join(__dirname, 'src/static/index.js');
20 | const outputPath = path.join(__dirname, 'dist');
21 | const outputFilename = isProd ? '[name]-[hash].js' : '[name].js'
22 |
23 | console.log('WEBPACK GO! Building for ' + TARGET_ENV);
24 |
25 | // common webpack config (valid for dev and prod)
26 | var commonConfig = {
27 | output: {
28 | path: outputPath,
29 | filename: `static/js/${outputFilename}`,
30 | },
31 | resolve: {
32 | extensions: ['.js', '.elm'],
33 | modules: ['node_modules']
34 | },
35 | module: {
36 | noParse: /\.elm$/,
37 | rules: [{
38 | test: /\.(eot|ttf|woff|woff2|svg)$/,
39 | use: 'file-loader?publicPath=../../&name=static/css/[hash].[ext]'
40 | }]
41 | },
42 | plugins: [
43 | new webpack.LoaderOptionsPlugin({
44 | options: {
45 | postcss: [autoprefixer()]
46 | }
47 | }),
48 | new HtmlWebpackPlugin({
49 | template: 'src/static/index.html',
50 | inject: 'body',
51 | filename: 'index.html'
52 | })
53 | ]
54 | }
55 |
56 | // additional webpack settings for local env (when invoked by 'npm start')
57 | if (isDev === true) {
58 | module.exports = merge(commonConfig, {
59 | entry: [
60 | 'webpack-dev-server/client?http://localhost:8080',
61 | entryPath
62 | ],
63 | devServer: {
64 | // serve index.html in place of 404 responses
65 | historyApiFallback: true,
66 | contentBase: './src',
67 | hot: true
68 | },
69 | module: {
70 | rules: [{
71 | test: /\.elm$/,
72 | exclude: [/elm-stuff/, /node_modules/],
73 | use: [{
74 | loader: 'elm-webpack-loader',
75 | options: {
76 | verbose: true,
77 | warn: true,
78 | debug: true
79 | }
80 | }]
81 | },{
82 | test: /\.sc?ss$/,
83 | use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader']
84 | }]
85 | }
86 | });
87 | }
88 |
89 | // additional webpack settings for prod env (when invoked via 'npm run build')
90 | if (isProd === true) {
91 | module.exports = merge(commonConfig, {
92 | entry: entryPath,
93 | module: {
94 | rules: [{
95 | test: /\.elm$/,
96 | exclude: [/elm-stuff/, /node_modules/],
97 | use: 'elm-webpack-loader'
98 | }, {
99 | test: /\.sc?ss$/,
100 | use: ExtractTextPlugin.extract({
101 | fallback: 'style-loader',
102 | use: ['css-loader', 'postcss-loader', 'sass-loader']
103 | })
104 | }]
105 | },
106 | plugins: [
107 | new ExtractTextPlugin({
108 | filename: 'static/css/[name]-[hash].css',
109 | allChunks: true,
110 | }),
111 | new CopyWebpackPlugin([{
112 | from: 'src/static/img/',
113 | to: 'static/img/'
114 | }, {
115 | from: 'src/favicon.ico'
116 | }]),
117 |
118 | // extract CSS into a separate file
119 | // minify & mangle JS/CSS
120 | new webpack.optimize.UglifyJsPlugin({
121 | minimize: true,
122 | compressor: {
123 | warnings: false
124 | }
125 | // mangle: true
126 | })
127 | ]
128 | });
129 | }
130 |
--------------------------------------------------------------------------------