const {
    createConfig,
    defineConstants,
    env,
    entryPoint,
    setOutput,
    sourceMaps,
    addPlugins,
    devServer,
    postcss,
    sass,
    css,
    typescript,
    extractText,
    customConfig,
    uglify,
    match,
    file,
    url
} = require('webpack-blocks');
const webpackMerge = require('webpack-merge');
const tslint = require('@webpack-blocks/tslint');
const autoprefixer = require('autoprefixer');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

const path = require('path');
const fs = require('fs');

const appPath = (...names) => path.join(process.cwd(), ...names);
const userConfig = require(appPath('webpack.config.js'));

const preprocessor = production => ({
    PRODUCTION: production,
    DEVELOPMENT: !production
});

const ifdef = (opts, block) => (context, utils) => prevConfig => {
    let conf = block(context, utils)(prevConfig);
    const index = conf.module.rules
        .map(
            (r, i) =>
                !Array.isArray(r.test) &&
                r.test.test('name.ts') &&
                r.enforce !== 'pre'
                    ? i
                    : -1
        )
        .reduce((acc, curr) => (acc === -1 && curr !== -1 ? curr : acc), -1);
    conf.module.rules[index].use.push({
        loader: 'ifdef-loader',
        options: opts
    });
    return conf;
};

const tsIfDef = production =>
    ifdef(
        preprocessor(production),
        typescript({
            useCache: true,
            cacheDirectory: 'node_modules/.cache/at-loader'
        })
    );

module.exports = webpackMerge(
    createConfig([
        tslint(),
        match(
            ['*.scss', '*.sass'],
            [
                postcss({
                    plugins: [autoprefixer({ browsers: ['last 2 versions'] })]
                }),
                sass({
                    includePaths: [appPath('node_modules')],
                    sourceMap: true
                }),
                env('production', [extractText('[name].[contenthash:8].css')])
            ]
        ),
        match(['*.eot', '*.ttf', '*.woff', '*.woff2'], [file()]),
        match(
            ['*.gif', '*.jpg', '*.jpeg', '*.png', '*.svg', '*.webp'],
            [url({ limit: 10000 })]
        ),
        defineConstants({
            'process.env.NODE_ENV': process.env.NODE_ENV
        }),
        addPlugins([
            new HtmlWebpackPlugin({
                template: './index.ejs',
                alwaysWriteToDisk: true,
                inject: true,
                favicon: 'public/favicon.png',
                hash: true
            }),
            new HtmlWebpackHarddiskPlugin({
                outputPath: appPath('public')
            }),
            new webpack.ProvidePlugin({
                Snabbdom: 'snabbdom-pragma'
            })
        ]),
        env('development', [
            tsIfDef(false),
            devServer({
                contentBase: appPath('public')
            }),
            sourceMaps(),
            addPlugins([new webpack.NamedModulesPlugin()])
        ]),
        env('production', [
            tsIfDef(true),
            uglify({
                parallel: true,
                cache: true,
                uglifyOptions: {
                    compress: {
                        warnings: false
                    }
                }
            }),
            addPlugins([
                new CleanWebpackPlugin([appPath('build')], {
                    root: process.cwd()
                }),
                new CopyWebpackPlugin([{ from: 'public', to: '' }])
            ])
        ]),
        env('test', [tsIfDef(true)])
    ]),
    userConfig
);

@@ -250,16 +250,29 @@
 %0A    url
+,%0A    resolve
 %0A%7D = req
@@ -1026,307 +1026,167 @@
 f = 
-(opts, block) =%3E (context, utils) =%3E prevConfig =%3E %7B%0A    let conf = block(context, utils)(prevConfig);%0A    const index = conf.module.rules%0A        .map(%0A            (r, i) =%3E%0A                !Array.isArray(r.test) &&%0A                r.test.test('name.ts') &&%0A                r.enforce !== 'pre'%0A    
+config =%3E (context, %7B addLoader %7D) =%3E%0A    addLoader(%7B%0A        test: /%5C.tsx?/,%0A        use: %5B%0A            %7B%0A                loader: 'awesome-typescript-loader'%0A
     
@@ -1197,15 +1197,10 @@
     
-    ? i
+%7D,
 %0A   
@@ -1212,20 +1212,60 @@
     
-        : -1
+%7B loader: 'ifdef-loader?' + JSON.stringify(config) %7D
 %0A   
@@ -1269,17 +1269,18 @@
         
-)
+%5D,
 %0A       
@@ -1285,116 +1285,66 @@
    .
-reduce((acc, curr) =%3E (acc === -1 && curr !== -1 ? curr : acc), -1);%0A    conf.module.rules%5Bindex%5D.use.pus
+..context.match%0A    %7D);%0A%0Aconst makeTs = prod =%3E%0A    matc
 h(
-%7B
 %0A   
@@ -1352,113 +1352,62 @@
     
-loader: 'ifdef-loader',%0A        options: opts%0A    %7D);%0A    return conf;%0A%7D;%0A%0Aconst tsIfDef = production =%3E%0A
+%5B'*.js', '*.jsx', '*.ts', '*.tsx'%5D,%0A        %5B%0A        
     
@@ -1412,25 +1412,16 @@
   ifdef(
-%0A        
 preproce
@@ -1433,17 +1433,16 @@
 prod
-uction),%0A
+)),%0A    
     
@@ -1458,16 +1458,20 @@
 cript(%7B%0A
+    
         
@@ -1498,24 +1498,28 @@
             
+    
 cacheDirecto
@@ -1558,26 +1558,40 @@
 er'%0A        
-%7D)
+    %7D)%0A        %5D
 %0A    );%0A%0Amod
@@ -1651,24 +1651,58 @@
   tslint(),%0A
+        resolve(%5B'.js', '.jsx'%5D),%0A
         matc
@@ -2931,23 +2931,22 @@
         
-tsIfDef
+makeTs
 (false),
@@ -3170,23 +3170,22 @@
         
-tsIfDef
+makeTs
 (true),%0A
@@ -3693,15 +3693,14 @@
 ', %5B
-tsIfDef
+makeTs
 (tru

Fix object spread not working in js files