Skip to content

Instantly share code, notes, and snippets.

@martinherweg
Last active May 29, 2021 08:07
Show Gist options
  • Save martinherweg/64ac8f3123044cb2777d6a9fcd9f6fdf to your computer and use it in GitHub Desktop.
Save martinherweg/64ac8f3123044cb2777d6a9fcd9f6fdf to your computer and use it in GitHub Desktop.
Webpack + BrowserSync + HMR
/**
|--------------------------------------------------------------------------
| gulp browser-sync
|--------------------------------------------------------------------------
*
* Browser Sync
* @description Refresh the Brwoser after File Change.
* Combined with webpack for HMR or Content Reload
*
* @package generator-mh-boilerplate
* @author Martin Herweg <[email protected]>
*/
/*
|--------------------------------------------------------------------------
| browser-sync.js
|--------------------------------------------------------------------------
*/
import config from '../../config.json';
import gulp from 'gulp';
import browserSync from 'browser-sync';
import webpack from 'webpack';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import webpackSettings from '../../webpack/webpack.config.babel';
import yargs from 'yargs';
const argv = yargs.argv;
const env = argv.env || 'development';
const browserSyncTask = () => {
if(env !== 'browser-sync') return;
//console.log(JSON.stringify(webpackSettings, ' ', 4));
const bundler = webpack(webpackSettings);
browserSync.init({
proxy: {
target: config.proxy,
ws: true,
},
ghostMode: {
clicks: true,
forms: true,
scroll: false,
},
logLevel: 'debug',
open: false,
stream: true,
ui: {
port: 8090,
},
middleware: [
webpackDevMiddleware(bundler, {
quiet: true,
path: webpackSettings.output.path,
publicPath: webpackSettings.output.publicPath,
stats: {
colors: true,
},
}),
webpackHotMiddleware(bundler, {
log: () => {},
}),
],
watchOptions: {
ignoreInitial: true
},
files: [
`${config.dist.views}**/*.{php,html,twig}`,
`${config.dist.images.base}**/*.{jpg,png,gif,svg}`,
`${config.dist}**/*.{css}`,
],
});
browserSync.watch(config.dist.base + '**/*.css', function(event, file) {
console.log(event, ' event on ', file);
if (event === 'change') {
browserSync.reload('*.css');
}
});
};
const browserSyncReload = () => {
browserSync.reload();
};
gulp.task('browser-sync', browserSyncTask);
gulp.task('bs-reload', browserSyncReload);
export { browserSyncTask, browserSyncReload };
import webpack from 'webpack';
import { getIfUtils, removeEmpty } from 'webpack-config-utils';
import path from 'path';
import config from '../config.json';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import WriteFilePlugin from 'write-file-webpack-plugin';
import StylelintPlugin from 'stylelint-webpack-plugin';
const { ifProduction, ifNotProduction } = getIfUtils(process.env.NODE_ENV);
/*
|--------------------------------------------------------------------------
| Setting some paths for our Application
|--------------------------------------------------------------------------
*/
const BASE_PATH = path.join(path.resolve(__dirname, '../'));
const ASSETS_ROOT = path.resolve(BASE_PATH, config.dist.base);
/*
|--------------------------------------------------------------------------
| Hot Middleware Client
|--------------------------------------------------------------------------
*/
const hot_client = 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000&reload=true&overlay=true';
/*
|--------------------------------------------------------------------------
| Defining Entry Points, could be used to manually split Parts of the Application, for example
| Admin Javascript and FrontEnd JavaScript
|--------------------------------------------------------------------------
*/
const entry_points = {
app: './src/js/app.js',
};
ifNotProduction(Object.keys(entry_points).forEach(entry => entry_points[entry] = [hot_client].concat(entry_points[entry])));
function assetsPath(_path) {
return path.posix.join('/assets/', _path);
}
let chunks = [];
const chunks_inject = [
{
filename: path.resolve(`${config.dist.views}parts/site-header.html`),
file: config.src.views + 'parts/site-header.html',
inject: false
},
{
filename: path.resolve(`${config.dist.views}parts/site-scripts.html`),
file: config.src.views + 'parts/site-scripts.html',
inject: false
},
];
chunks_inject.forEach((chunk) => {
const plugin = new HtmlWebpackPlugin({
filename: chunk.filename,
template: chunk.file,
inject: chunk.inject,
minify: false,
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency',
});
chunks.push(plugin);
});
const extractSass = new ExtractTextPlugin({
filename: assetsPath('css/[name].css'),
});
/*
|--------------------------------------------------------------------------
| return webpack config object
|--------------------------------------------------------------------------
*/
export default {
devtool: ifProduction('source-map', 'cheap-module-eval-source-map'),
context: BASE_PATH,
// entry is a function so that we can use environment variables
entry: removeEmpty(entry_points),
output: {
path: ASSETS_ROOT,
publicPath: '',
filename: assetsPath('js/[name].js'),
},
resolve: {
extensions: ['.js', '.vue', '.json'],
modules: [
resolve('src'),
resolve('node_modules'),
],
alias: {
'vue$': 'vue/dist/vue.common.js',
'src': resolve('src'),
},
},
module: {
rules: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: resolve('src'),
options: {
formatter: require('eslint-formatter-pretty'),
},
},
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.js$/,
loader: 'babel-loader',
include: resolve('src'),
},
{
test: /\.json$/,
loader: 'json-loader',
},
{
test: /\.scss$/,
include: resolve('src/scss'),
exclude: [resolve('node_modules'), resolve('dist/')],
loader: extractSass.extract({
loader: [
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
}),
},
],
},
plugins: removeEmpty([
ifProduction(new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"',
},
})),
new webpack.HotModuleReplacementPlugin(),
new StylelintPlugin({
context: resolve('src/scss/'),
syntax: 'scss',
}),
extractSass,
...chunks,
new WriteFilePlugin({
test: /^(?!.+(?:hot-update.(js|json))).+$/,
}),
]),
};
function resolve(dir) {
return path.join(__dirname, '..', dir);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment