User Tools

Site Tools


webpack_complete_webdevelopment_config
→ Slide 1

Webpack / Yarn Web Development Config

↓ Slide 2

What it does ...

  • Build Webfont and corresponding SCSS (Webfont.scss.njk → compiles to →_webfont.scss)
  • Compile and process SCSS
    • Lint
    • Concatenate
    • Autoprefix
    • Minify
    • Compress
  • Compile and process Javascript
    • Babel (transpile to ES2015)
    • Concatenate
    • Uglify
    • Compress
  • Generate KSS Styleguide
    • Icons included
    • Using custom template (index.hbs, kss-assets/kss.scss)
↓ Slide 3

Yarn

  • Define “workspaces” to install packages recursively
    • Workspace will be linked to ./node_modules/JoRo.Library (package.json → “name”)
    • Dependencies end up in ./node_modules/ :!:
  • Centralize/unify build commands
  • Compatible with NPM but creates a yarn.lock file
  • Commands are slightly different than NPMs (e.g. yarn add packageName)
Commands
- development # Build assets for development
   webpack
- livereload  # Run PHP Server and watch for changes
   FLOW_CONTEXT=Development/Livereload ./flow server:run | webpack --watch
- production  # Build assets for production
   NODE_ENV='production' webpack
- watch       # Watch for changes and build files accordingly
   webpack --watch
↓ Slide 4

package.json

package.json
{
    "name": "JoRo.Library",
    "version": "1.0.0",
    "description": "Template for Library Oberroth",
    "scripts": {
        "production": "NODE_ENV='production' webpack",
        "development": "webpack",
        "watch": "webpack --watch",
        "livereload": "FLOW_CONTEXT=Development/Livereload ./flow server:run | webpack --watch"
    },
    "private": true,
    "workspaces": [
        "./Packages/Sites/JoRo.Library/Resources/Private/Library/"
    ],
    "author": "Jochen Roth",
    "license": "MIT",
    "dependencies": {
        "ajv": "^6.0.1",
        "babel-core": "^6.26.0",
        "babel-loader": "^7.1.2",
        "babel-preset-env": "^1.6.1",
        "babel-preset-es2015": "^6.24.1",
        "caniuse-lite": "^1.0.30000697",
        "compression-webpack-plugin": "^1.1.3",
        "css-loader": "^0.28.9",
        "cssnano": "^3.10.0",
        "extract-text-webpack-plugin": "^3.0.2",
        "foundation-icons": "^1.0.1",
        "foundation-sites": "^6.4.3",
        "image-size": "^0.6.2",
        "jquery": "^3.2.1",
        "jshint": "^2.9.5",
        "jshint-loader": "^0.8.4",
        "kss": "^3.0.0-beta.18",
        "kss-webpack-plugin": "^1.3.0",
        "node-sass": "^4.7.2",
        "postcss-cssnext": "^3.0.2",
        "postcss-import": "^11.0.0",
        "postcss-loader": "^2.0.10",
        "postcss-url": "^7.3.0",
        "precss": "^3.0.0",
        "sanitize-filename": "^1.6.1",
        "sass-lint": "^1.12.1",
        "sass-loader": "^6.0.6",
        "sasslint-webpack-plugin": "^1.0.4",
        "style-loader": "^0.18.2",
        "uglifyjs-webpack-plugin": "^1.1.6",
        "webpack": "^3.10.0",
        "webpack-sass": "^2.2.1",
        "webpack-watch-livereload-plugin": "^0.0.1",
        "webpack-webfont": "0.0.1-alpha.10",
        "what-input": "^4.3.1"
    },
    "devDependencies": {}
}
↓ Slide 5

webpack.config.js

webpack.config.js
const path = require("path");
const webpack = require("webpack");
const sassLintPlugin = require('sasslint-webpack-plugin');
const CompressionPlugin = require("compression-webpack-plugin");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const WebFontPlugin = require('webpack-webfont/dist/WebfontPlugin').default;
const WatchLiveReloadPlugin = require('webpack-watch-livereload-plugin');
const KssWebpackPlugin = require('kss-webpack-plugin');
 
/**
 * Paths for your TYPO3/Neos Project
 * @type string
 */
const corePluginBase = './node_modules/JoRo.Library/';
const corePluginTarget = './Packages/Sites/JoRo.Library/Resources/Public/';
 
if (process.env.NODE_ENV === undefined) {
    process.env.NODE_ENV = 'develpoment'
}
 
/**
 * Plugins enabled/disabled depending on contextSwitch (Production = true / Development = false)
 * Make sure context ist always set. Default 'development'
 */
const contextSwitch = (process.env.NODE_ENV == 'production' ? true : false);
 
/**
 * Define Array and pass it on to webpacks "module.exports.plugins: []" property
 * @type {Array}
 */
let pluginConfig = [];
 
/**
 * Set output path for SASS compilation
 * @see https://github.com/webpack-contrib/extract-text-webpack-plugin#options
 */
pluginConfig[0] = new ExtractTextPlugin({
    filename: corePluginTarget + 'Styles/app.css'
});
const extractPlugin = pluginConfig[0];
 
pluginConfig[8] = new ExtractTextPlugin({
    filename: corePluginTarget + 'Styles/kss.css'
});
const extractKssPlugin = pluginConfig[8];
 
/**
 * Lint/Validate sass code
 * @see https://github.com/alleyinteractive/sasslint-webpack-plugin#options
 */
pluginConfig[2] = new sassLintPlugin({
    glob: './Scss/**/*.s?(a|c)ss',
    ignoreFiles: [path.resolve(corePluginBase, 'Scss/_webfont.scss')],
    ignorePlugins: ['extract-text-webpack-plugin']
});
 
/**
 * Generate Icon Font
 * @see https://www.npmjs.com/package/webpack-webfont#options
 */
pluginConfig[3] = new WebFontPlugin({
    files: '{./node_modules/foundation-icons/svgs/,./Svg}**/*.svg',
    fontName: 'icon',
    classNmw: 'icon',
    cssFormat: 'template',
    template: path.resolve(corePluginBase, 'Templates/Webfont.scss.njk'),
    cssTemplateFontPath: '../Fonts/',
    dest: {
        fontsDir: corePluginTarget + 'Fonts/',
        stylesDir: path.resolve(corePluginBase, 'Scss/'),
        outputFilename: '_webfont.scss',
    }
});
 
/**
 * Uglify/Minify Javascript based on UglifyJS2
 * @see https://github.com/webpack-contrib/uglifyjs-webpack-plugin#options
 */
pluginConfig[4] = (contextSwitch == true ? new UglifyJsPlugin() : '');
 
/**
 * Compress js/css files using gzip (*.gz)
 * @see https://github.com/webpack-contrib/compression-webpack-plugin#options
 */
pluginConfig[5] = (contextSwitch == true ? new CompressionPlugin({asset: '[path].gz[query]'}) : '');
 
 
/**
 * Generate KSS Styleguide
 * @see https://github.com/kss-node/kss-node#using-the-command-line-tool
 */
pluginConfig[6] = new KssWebpackPlugin({
    source: [corePluginBase + 'Scss/', corePluginBase + 'Templates/Styleguide/kss-assets/'],
    destination: corePluginTarget + "Styleguide",
    builder: corePluginBase + 'Templates/Styleguide/',
    homepage: '../Templates/homepage.md',
    title: "knallimall.org",
    css: ['../Styles/app.css'],
    js: ['../JavaScript/script.js'],
    custom: ['Icons', 'Colorpicker'],
    extend: corePluginBase + 'Templates/Styleguide/helpers/'
});
 
/**
 * Reload assets in Browser when changed - Make sure http://localhost:35729/livereload.js included
 * @context Development/Livereload
 * @see https://github.com/napcs/node-livereload#command-line-options
 */
pluginConfig[7] = new WatchLiveReloadPlugin({
    files: [
        // Replace these globs with yours
        corePluginTarget + 'Styles/**/*.css',
        corePluginTarget + 'JavaScript/**/*.js'
    ]
}),
 
/**
 * Remove empty array values - empty values cause webpack plugin config to fail
 * @func pluginConfig
 */
pluginConfig = pluginConfig.filter(function (x) {
    return (x !== (undefined || null || ''));
});
 
 
const extractConfig = {
    disable: false,
    fallback: "style-loader",
    use: [
        {
            loader: 'css-loader',
            options: {
                url: false,
                importLoaders: 1,
                minimize: contextSwitch,
                sourceMap: contextSwitch
            }
        },
        {
            loader: 'postcss-loader',
            options: {
                plugins: (loader) => [
                    require('postcss-import')({addDependencyTo: webpack}),
                    require('postcss-url'),
                    require('postcss-cssnext')({
                        browsers: ['last 2 versions', 'ie >= 9'],
                    }),
                ]
            }
        },
        {
            loader: "sass-loader",
            options: {
                context: '/',
                includePaths: [
                    path.resolve('./node_modules/foundation-sites/scss'),
                    path.resolve(corePluginBase + 'Scss')
                ]
            }
        }
    ],
};
 
module.exports = {
    entry: {
        script: [corePluginBase + 'JavaScript/script.js'],
    },
    output: {
        path: __dirname,
        filename: corePluginTarget + "JavaScript/script.js"
    },
    resolve: {
        extensions: ['.js', '.scss'],
        modules: [
            path.resolve('./node_modules/')
        ],
    },
    watchOptions: {
        ignored: [ /Styleguide/, /node_modules/, /Data/, "/Web/"]
    },
    module: {
        rules: [{
            test: /\.js$/,
            exclude: /node_modules/,
            enforce: "pre",
            loader: "jshint-loader",
            options: {
                failOnHint: false,
                // Set to true to make sure if it fails build in GitLab will fail as well
                emitErrors: true,
                // reporter: function(errors) { console.log(errors) },
                // Use all options described here: http://jshint.com/docs/options/
                esversion: 6
            }
        }, {
            test: '/\.js$/',
            use: [{
                loader: 'babel-loader',
                options: {
                    presets: ['es2015']
                }
            }]
        }, {
            test: /app\.scss/,
            use: extractPlugin.extract(extractConfig),
        }, {
            test: /kss\.scss/,
            use: extractKssPlugin.extract(extractConfig),
        }
        ]
    },
    plugins: pluginConfig
};
↓ Slide 6

The Good, the Bad ...

webpack_complete_webdevelopment_config.txt · Last modified: 2018/02/05 23:48 by admin