cordova-elm-template-jumpstart
Version:
Cordova template to jumpstart development using Elm and Webpack
280 lines (274 loc) • 8.38 kB
JavaScript
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const webpack = require("webpack");
const os = require("os");
const path = require("path");
const _ = require("lodash");
const keysToConstCase = (map) => _.mapKeys(map, (val,key) => _.toUpper(_.snakeCase(key)));
const fs = require("fs");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ClosureCompilerPlugin = require('webpack-closure-compiler');
const OptimizeJsPlugin = require("optimize-js-plugin");
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
const packageJson = keysToConstCase(require("./package.json"));
const optional = require("optional");
const googleServices = keysToConstCase(optional("./google-services.json") || {});
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const WebpackShellPlugin = require('webpack-shell-plugin');
googleServices.FB_PROJECT_ID = _.get(googleServices, "project_info.project_id");
googleServices.FB_MESSAGING_SENDER_ID = _.get(googleServices, "project_info.project_number");
const ENV = process.env['NODE_ENV'] || 'development';
const IS_DEV = ENV == 'development';
const notDev = (it) => IS_DEV ? null : it;
const onlyDev = (it) => IS_DEV ? it : null;
const node_modules = /\/(?:node_modules|elm_stuff)\//;
const localConfig = fs.existsSync("./local.config.json") ? require("./local.config.json") : {};
const babel = {
loader: 'babel-loader',
options: {
presets: _.compact(['env', 'bluebird', notDev('minify') ]),
plugins: _.compact([
"transform-strict-mode",
"transform-undefined-to-void",
"transform-node-env-inline",
notDev('transform-remove-console'),
notDev('transform-remove-debugger'),
]),
cacheDirectory: IS_DEV,
}
}
const urlLoader = {
loader: 'url-loader',
options: {
limit: IS_DEV ? 1024 * 1024 : 32 * 1024 - 1, // 32k is the maximum safe size for data uris on old browsers
hash: 'sha256',
digest: 'hex',
name: '[path][name].' + (IS_DEV ? "dev" : '[sha256:hash:base62]') + '.[ext]',
useRelativePath: false,
},
}
const imageMinLoader = {
loader: 'image-webpack-loader',
options: {
mozjpeg: {
quality: 65,
interlaced: true,
},
pngquant:{
quality: "65-90",
speed: 1
},
svgo:{
},
gifsicle: {
optimizationLevel: 7,
interlaced: true,
},
optipng: {
optimizationLevel: 7,
},
},
}
const scssLoaders = [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 3,
sourceMap: true,
minimize: !IS_DEV,
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: true,
}
},
'resolve-url-loader',
{
loader: 'sass-loader',
options: {
sourceMap: true,
sourceMapContents: true,
sourceMapEmbed: true,
precision: 2,
sourceComments: IS_DEV,
outputStyle: IS_DEV ? 'nested' : 'compressed',
includePaths: [
path.resolve(__dirname, 'node_modules'),
path.resolve(__dirname, 'src', 'scss'),
],
},
},
]
module.exports = {
devtool: 'source-map',
context: path.resolve(__dirname),
watchOptions: {
ignored: [
/node_modules\//,
/\.git\//,
/www\//,
/platforms\//,
/plugins\//,
/hooks\//,
/scripts\//
]
},
entry: {
bootstrap : [
path.resolve(__dirname, "src", "vendor", "jquery.js"),
path.resolve(__dirname, "src", "vendor", "popper.js"),
"bootstrap",
],
compatibility: [
'babel-polyfill',
path.resolve(__dirname, "src", "vendor", "svg4everybody.js"),
path.resolve(__dirname, "src", "vendor", "touchEmulator.js"),
],
app: [
path.resolve(__dirname, "src", "index.js"),
],
style: [
path.resolve(__dirname, "src", "scss", "index.scss"),
],
},
output: {
path: path.resolve(__dirname, 'www'),
chunkFilename: 'chunk.[id].' + (IS_DEV ? "dev" : '[chunkhash]') + '.js',
filename: '[name].' + (IS_DEV ? "dev" : '[chunkhash]') + '.js',
crossOriginLoading: 'anonymous',
hashFunction: 'sha256',
pathinfo: IS_DEV,
strictModuleExceptionHandling: true
},
module: {
rules: [
{
test: /\.json5?$/i,
use: [ 'json5-loader' ],
},
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: _.compact([
urlLoader,
notDev(imageMinLoader),
]),
},
{
test: /\.elm$/i,
use: [
babel,
{
loader: 'elm-webpack-loader',
options: {
cwd: path.resolve(__dirname, "src", "elm"),
warn: IS_DEV,
debug: IS_DEV,
verbose: true,
pathToMake: path.resolve(__dirname, "script", "unbuffer-elm-make"),
}
},
],
},
{
test: /\.jsx?$/i,
exclude: node_modules,
use: [
babel,
]
},
{
test: /\.(eot|ttf|woff2?)(\?.*)?$/i,
loader: [
urlLoader,
],
},
{
test: /\.s?css$/i,
use: scssLoaders,
},
],
},
plugins: _.compact([
new FaviconsWebpackPlugin({
logo: path.resolve(__dirname, 'icon.png'),
prefix: 'favicon/' + (IS_DEV ? "dev" : '[hash]') + '/',
emitStats: false,
persistentCache: false,
inject: true,
background: '#fff',
title: 'Elm-Based Cordova App',
icons: {
android: !IS_DEV,
appleIcon: !IS_DEV,
appleStartup: !IS_DEV,
coast: !IS_DEV,
favicons: true,
firefox: !IS_DEV,
windows: !IS_DEV,
yandex: !IS_DEV
}
}),
new webpack.DefinePlugin(_.mapValues(_.merge({
// Add in any "constants" that you want. Note that NODE_ENV is already handled by Babel
// Also, you have all of package.json (but the keys are constant-cased).
// Finally, it loads 'local.config.json' and merges those things in.
MIN_SPLASH_MS: 5000, // Minimum amount of time for a splash screen to be up
IS_DEV: IS_DEV, // Note for a development environment
// Google Analytics constants
GOOGLE_TRACKING_ID: null, // Defining this to truthy enables Google tracking in production
GA_CUSTOM_DIM_CORDOVA_VERSION: 1, // Defining this to >0 sets the Cordova version as a custom dimension
GA_CUSTOM_DIM_DEVICE_MODEL: 2, // Defining this to >0 sets the hardware device model as a custom dimension
GA_CUSTOM_DIM_CONNECTIVITY: 3, // Defining this to >0 sets the Internet connectivity as a custom dimension
GA_CUSTOM_DIM_PLATFORM: 4, // Defining this to >0 sets the OS platform (iOS/Android/web) as a custom dimension
GA_CUSTOM_DIM_DEVICE_UUID: 5, // Defining this to >0 sets the device UUID as a custom dimension
GA_CUSTOM_DIM_DEVICE_VERSION: 6, // Defining this to >0 sets the OS/device version as a custom dimension
GA_CUSTOM_DIM_DEVICE_MANUFACTURER: 7, // Defining this to >0 sets the manufacturer as a custom dimension
}, googleServices, packageJson, localConfig), it => JSON.stringify(it))),
new UglifyJSPlugin({
parallel: true,
sourceMap: true,
uglifyOptions: {
compress: !IS_DEV,
output: {
comments: IS_DEV,
beautify: IS_DEV,
},
ecma: 8,
}
}),
notDev(new OptimizeJsPlugin({
sourceMap: true,
})),
new HtmlWebpackPlugin({
inject: 'head',
minify: notDev({}),
filename: "index.html",
template: path.resolve("src", "index.html"),
chunkSortMode: "dependency"
}),
new CopyWebpackPlugin([
{ from: './splash.png', to: './splash.png' },
], { debug: 'info' }),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: 2,
children: true,
minSize: 0,
}),
new WebpackShellPlugin({ // See https://github.com/kevlened/copy-webpack-plugin/issues/15
onBuildStart: [
'echo "Cleaning up previous build leftovers"',
'rm -r -v -f ./www/*',
],
onBuildEnd: [
'echo "Copying the files to the browser"',
'cp -r -v -f ./www ./platforms/browser/',
'echo "Build complete"',
],
dev: false // Weird name for executing only once
}),
]),
};