Created
August 1, 2019 10:19
-
-
Save davidhellmann/e6729d4d06567cec079bc9f941448182 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Webpack Config | |
* | |
* @package generator-baukasten | |
* @author David Hellmann <[email protected]> | |
*/ | |
import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer'; | |
import {getIfUtils, removeEmpty} from 'webpack-config-utils'; | |
import ExtractTextPlugin from 'extract-text-webpack-plugin'; | |
import FriendlyErrorsWebpackPlugin from 'friendly-errors-webpack-plugin'; | |
import HtmlWebpackPlugin from 'html-webpack-plugin'; | |
import OptimizeCSSPlugin from 'optimize-css-assets-webpack-plugin'; | |
import EasyStylelintPlugin from 'easy-stylelint-plugin'; | |
import webpack from 'webpack'; | |
import WriteFilePlugin from 'write-file-webpack-plugin'; | |
import path from 'path'; | |
import yargs from 'yargs'; | |
import pkg from '../package.json'; | |
const {argv} = yargs; | |
const site = argv.site || 'hr'; | |
let subFolder = 'SITE_HR/'; | |
let jsFile = 'app_hr.js'; | |
let entryName = 'app_hr'; | |
if (site === 'b2c') { | |
subFolder = 'SITE_B2C/'; | |
jsFile = 'app.js'; | |
entryName = 'app'; | |
} | |
console.log({site, subFolder, jsFile}); | |
// get absolute path of files based on root | |
function resolve(dir) { | |
return path.resolve(__dirname, `../${dir}`); | |
} | |
const {ifProduction, ifDevelopment} = getIfUtils(process.env.NODE_ENV); | |
// der string wird benötigt um hot reloading nutzen zu können | |
// der wird einfach an den entry point gehangen | |
const hotClient = | |
'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000&reload=true&overlay=true'; | |
// hier holen wir uns die dateien in die wir unsere Build Files | |
// (app.23r23fwef23r.js und app.323r233.css zum beispiel injecten wollen, | |
// also eine datei für den header und eine für den footer) | |
// dann definieren wir noch wo die hinsollen und | |
// bauen eine funktion die das plugin ausspuckt | |
const injectFolder = `${subFolder}webpack`; | |
const fileExtension = '.twig'; | |
const headerFilenameSRC = 'webpack-header'; | |
const headerFilenameDIST = 'webpack-header'; | |
const scriptsFilenameSRC = 'webpack-scripts'; | |
const scriptsFilenameDIST = 'webpack-scripts'; | |
const folderDIST = pkg.dist.markup; | |
const injectTemplates = [ | |
{ | |
// DIST File | |
filename: resolve(`${folderDIST + injectFolder}/${headerFilenameDIST}${fileExtension}`), | |
// SRC File | |
file: `${pkg.src.templates + injectFolder}/${headerFilenameSRC}${fileExtension}`, | |
inject: false, | |
}, | |
{ | |
// DIST File | |
filename: resolve(`${folderDIST + injectFolder}/${scriptsFilenameDIST}${fileExtension}`), | |
// SRC File | |
file: `${pkg.src.templates + injectFolder}/${scriptsFilenameSRC}${fileExtension}`, | |
inject: false, | |
}, | |
]; | |
// Leeres Array welches wir später mittels ...restParameter | |
// in die Plugins mit einfügen | |
const chunks = []; | |
// Befüllen des obigen Arrays mit den chunks die wir definiert haben. | |
injectTemplates.forEach(chunk => { | |
const plugin = new HtmlWebpackPlugin({ | |
filename: chunk.filename, | |
template: chunk.file, | |
inject: chunk.inject, | |
minify: false, | |
chunksSortMode: 'dependency', | |
}); | |
chunks.push(plugin); | |
}); | |
// Sass Resources Loader | |
// Damit werden die angegebenen Dateien automatisch injected | |
// Das ist besonders praktisch für Vue files. Wenn du deine Tools und Settings | |
// benutzen willst aber nicht in jn der Componente die entsprechenden Dateien includen willst. | |
// Definieren wir hier oben als variable um sie evtl. später auch anderweitig nutzen zu können. | |
const sassResourcesLoader = { | |
loader: 'sass-resources-loader', | |
options: { | |
resources: [resolve(`${pkg.src.css}_settings.scss`), resolve(`${pkg.src.css}_tools.scss`)], | |
}, | |
}; | |
// SCSS Loader Config | |
const SCSS_LOADERS = [ | |
{ | |
loader: 'css-loader', | |
options: { | |
autoprefixer: false, | |
sourceMap: true, | |
importLoaders: 2, | |
url: true, | |
}, | |
}, | |
{ | |
loader: 'postcss-loader', | |
options: { | |
sourceMap: true, | |
}, | |
}, | |
{ | |
loader: 'sass-loader', | |
options: { | |
sourceMap: true, | |
}, | |
}, | |
]; | |
// CSS Loader Config | |
const CSS_LOADERS = [ | |
{ | |
loader: 'css-loader', | |
options: { | |
autoprefixer: false, | |
sourceMap: true, | |
importLoaders: 2, | |
url: true, | |
}, | |
}, | |
{ | |
loader: 'postcss-loader', | |
options: { | |
sourceMap: true, | |
}, | |
}, | |
]; | |
module.exports = { | |
mode: ifProduction('production', 'development'), | |
devtool: ifProduction('#source-map', '#eval'), | |
// javascript file in dem alles importiert wird, erstmal der simpelste zweck | |
// hier ein object, jede datei die hier definiert wird kommt als eigener outputh raus, | |
// also wenn du eine admin.js im src folder machst kommt eine admin.js in den dist folder raus | |
entry: { | |
[entryName]: ifDevelopment( | |
[resolve(`${pkg.src.js}${jsFile}`), hotClient], | |
resolve(`${pkg.src.js}${jsFile}`), | |
), | |
}, | |
output: { | |
// in das verzeichnis kommt alles rein | |
path: resolve(`${pkg.dist.base}assets/`), | |
publicPath: '/assets/', | |
// [name] sorgt dafür das der key aus dem entry object als dateiname benutzt wird | |
filename: ifProduction(`js/${subFolder}[name].[hash].min.js`, `js/${subFolder}[name].js`), | |
chunkFilename: `js/${subFolder}[name].[chunkhash].js`, | |
hotUpdateChunkFilename: '[id].[hash].hot-update.js', | |
hotUpdateMainFilename: '[hash].hot-update.json', | |
}, | |
resolve: { | |
extensions: ['.js', '.json', '.vue'], | |
// hier werden verzeichnisse angegeben in denen gesucht wird wenn du was importierst | |
// also import from 'foo/bar' dann schaut er in diesen verzeichnissen wo bar.js sein könnte | |
modules: [resolve(pkg.src.base), resolve('node_modules')], | |
// aliase sind ne schöne sache du kannst dir hier zum beispiel auch deinen modules pfad einbauen | |
// nehmen wir dein Alias hieße Modules, dann kannst du in JS Files | |
// einfach import foo from 'Modules/foo/foo'; machen | |
// mit Storm hast du auch Autocomplete in diesen Aliasen | |
alias: { | |
// alias der auf den Standalone Build geht, falls du Vue ausserhalb von | |
// Single File Components nutzen möchtest | |
vue$: 'vue/dist/vue.esm.js', | |
CSS: resolve(pkg.src.css), | |
'@': resolve(pkg.src.base), | |
JS: resolve(pkg.src.js), | |
FONTS: resolve(pkg.src.fonts), | |
ASSETS: resolve(pkg.src.images.base), | |
}, | |
}, | |
optimization: { | |
splitChunks: { | |
chunks: 'all', | |
}, | |
}, | |
module: { | |
// hier wird definiert mit welcher datei was gemacht wird | |
// das passiert über loader, hier kommen auch vue, css etc. rein später | |
rules: [ | |
// als erstes ESLint für .js und .vue dateien | |
{ | |
test: /\.(js|vue)$/, | |
loader: 'eslint-loader', | |
options: { | |
failOnError: false, | |
}, | |
// damit weiß webpack das dieser loader vor allen anderen kommen soll | |
enforce: 'pre', | |
include: resolve(pkg.src.base), | |
}, | |
// hier dann das eigentliche laden von JS | |
{ | |
test: /\.js/, | |
loader: 'babel-loader', | |
include: resolve(pkg.src.base), | |
}, | |
// Vue Loader Wohooo | |
{ | |
test: /\.vue$/, | |
loader: 'vue-loader', | |
include: resolve(pkg.src.base), | |
options: { | |
loaders: { | |
scss: ifProduction( | |
ExtractTextPlugin.extract({ | |
use: [...SCSS_LOADERS, sassResourcesLoader], | |
}), | |
['vue-style-loader', ...SCSS_LOADERS, sassResourcesLoader], | |
), | |
}, | |
}, | |
}, | |
// SCSS Loading | |
{ | |
test: /\.scss$/, | |
use: ifProduction( | |
// extract Text Plugin für Production | |
ExtractTextPlugin.extract({ | |
use: [...SCSS_LOADERS, sassResourcesLoader], | |
fallback: 'style-loader', | |
}), | |
// im development fügen wir den style-loader ein um styles zu injecten | |
[ | |
{ | |
loader: 'style-loader', | |
options: { | |
sourceMap: true, | |
}, | |
}, | |
...SCSS_LOADERS, | |
], | |
), | |
include: resolve(pkg.src.base), | |
}, | |
// CSS Loading | |
{ | |
test: /\.css$/, | |
use: ifProduction( | |
// extract Text Plugin für Production | |
ExtractTextPlugin.extract({ | |
use: [...CSS_LOADERS], | |
fallback: 'style-loader', | |
}), | |
// im development fügen wir den style-loader ein um styles zu injecten | |
[ | |
{ | |
loader: 'style-loader', | |
options: { | |
sourceMap: true, | |
}, | |
}, | |
...CSS_LOADERS, | |
], | |
), | |
include: resolve(pkg.src.base), | |
}, | |
{ | |
test: /\.(png|jpg|gif|svg)$/, | |
include: resolve(pkg.src.base), | |
loader: 'url-loader', | |
options: { | |
limit: 10000, | |
name: filePath => { | |
const filename = path.basename(filePath); | |
const folder = path.relative(pkg.src.images.base, filePath).replace(filename, ''); | |
return `${folder}[name].[hash:4].[ext]`; | |
}, | |
}, | |
}, | |
{ | |
// Match woff2 in addition to patterns like .woff?v=1.1.1. | |
test: /\.(woff|woff2|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/, | |
loader: 'url-loader', | |
include: resolve(pkg.src.base), | |
options: { | |
// Limit at 10k. Above that it emits separate files | |
limit: 10000, | |
// url-loader sets mimetype if it's passed. | |
// Without this it derives it from the file extension | |
mimetype: 'application/font-woff', | |
// Output below fonts directory | |
name: 'fonts/[name].[ext]', | |
}, | |
}, | |
], | |
}, | |
plugins: removeEmpty([ | |
// Dateiname für das Extracted CSS von Vue | |
// wenn du dein eigenes css über webpack laufen lässt kommen beide in eine datei | |
ifProduction( | |
new ExtractTextPlugin({ | |
filename: `css/${subFolder}[name].[chunkhash].min.css`, | |
allChunks: true, | |
}), | |
), | |
// nötig für HMR | |
ifDevelopment(new webpack.HotModuleReplacementPlugin()), | |
new FriendlyErrorsWebpackPlugin(), | |
// Webpack Bundle Analyzer | |
ifProduction( | |
new BundleAnalyzerPlugin({ | |
analyzerMode: 'disabled', | |
generateStatsFile: true, | |
statsFilename: resolve('webpack/stats.json'), | |
logLevel: 'info', | |
}), | |
), | |
// Optimize CSS Asset Stuff | |
ifProduction( | |
new OptimizeCSSPlugin({ | |
cssProcessorOptions: { | |
safe: true, | |
}, | |
}), | |
), | |
new EasyStylelintPlugin({ | |
context: resolve(pkg.src.base), | |
}), | |
// Hier das Array der Chunks mit dem Plugin Array zusammenfügen | |
...chunks, | |
new WriteFilePlugin({ | |
log: false, | |
test: /^(?!.+(?:hot-update.(js|json))).+$/, | |
}), | |
]), | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment