Skip to content

Commit

Permalink
Revert "Improvements"
Browse files Browse the repository at this point in the history
This reverts commit d2836ce.
  • Loading branch information
pavelloz committed Apr 10, 2024
1 parent a46fae3 commit d488282
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 84 deletions.
12 changes: 0 additions & 12 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
## 10 April 2024

- Added sourceMaps (dev, prod)
- Added non-delayed example of prefetched file
- Changed `console.log` copy
- Small cleanup in webpack config

* `html-bundler-webpack-plugin`
- Always inline entry points (JS and CSS)
- No longer emits inlined files
- Improved readme to explain current behavior and how to customize it

## 17 March 2024

- Improved examples
Expand Down
25 changes: 5 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,17 @@ Having this boilerplate ready to run on your machine is as easy as typing:
### npm/pnpm tasks

- `pnpm start` - runs dev server on `http://localhost:8888` and reloads the browser on changes
- `pnpm build` - build assets in `production` mode, ready to deploy
- `pnpm build` - build assets in production mode, ready to deploy

## Webpack setup includes

- JS and CSS transpilation and minification done by ESBuild (meaning: its FAST)
- JS and CSS transpilation and minification done by ESBuild (FAST)
- CSS extraction using `mini-css-extract-plugin`
- HTML generation using `html-bundler-webpack-plugin`
- SourceMaps:
- In `development` mode: they are inlined to provide you the best development experience
- In `production` mode: they are emitted next to the source .js file but not referenced inside of it. You should take care of uploading them to your error reporting tool
- Examples of some webpack specific features are also included:
- Examples:
- Prefetched chunk, if you want to load faster critical parts of your build
- Asynchronously loaded chunks, to not block page rendering when loading/parsing/executing
- Named chunks if you want your chunks to have pretty names instead of SHA (ie. `2aae6c35c94fcfb415dbe95f408b9ce91ee846ed.js`)

## Inlined JS/CSS entry points

Webpack (or rather, `html-bundler-webpack-plugin`) will inline entry points of JS and CSS into the HTML file. This is concious decision because entry points are small and rest of the app is loaded asynchronously. I highly recommend keeping it this way and working loading your code effectively.

1. CSS: TailwindCSS is small and won't grow much
a. When you import 3rd party code, you should import css in async loaded chunk, so the CSS is extracted to a separate file
2. JS: You should leverage webpack async chunks to split your app into smaller chunks (which are emitted and not inlined). See examples for more guidance.

Inlined entry points are not emitted to dist/ directory - they are only inlined. This also can be configured in `html-bundler-webpack-plugin`.

If for whatever reason you do not want this behavior here is [the documentation to change it](https://github.com/webdiscus/html-bundler-webpack-plugin?tab=readme-ov-file#recipe-inline-js).
- Asynchronously loaded chunks, to block page rendering when loading/parsing/executing
- Named chunks if you dont want your chunks to look like `2aae6c35c94fcfb415dbe95f408b9ce91ee846ed.js`

## PostCSS setup includes

Expand Down
16 changes: 5 additions & 11 deletions src/js/app.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import(/* webpackChunkName: "deferred-module" */ './deferred-module').then((module) => module.default());

import(/* webpackChunkName: "prefetched-and-delayed-module", webpackPrefetch: true */ './prefetched-module').then(
(module) => {
setTimeout(() => {
module.default(`Executed: Prefetched module, delayed by 2 seconds`);
}, 2000);
}
);
import(/* webpackChunkName: "defered-module" */ './defered-module').then((module) => module.default());

import(/* webpackChunkName: "prefetched-module", webpackPrefetch: true */ './prefetched-module').then((module) => {
module.default();
setTimeout(() => {
module.default();
}, 2000);
});

console.log('Executed: app.js');
console.log('Hello from app.js');
2 changes: 1 addition & 1 deletion src/js/deferred-module.js → src/js/defered-module.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const module = () => {
console.log('Executed: Deferred module!');
console.log('Hello from defered module!');
};

export default module;
4 changes: 2 additions & 2 deletions src/js/prefetched-module.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const module = (msg = 'Executed: Prefetched module!') => {
console.log(msg);
const module = () => {
console.log('Hello from prefetched module!');
};

export default module;
40 changes: 20 additions & 20 deletions tailwind.config.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
const defaultTheme = require('tailwindcss/defaultTheme');

module.exports = {
content: ['./src/**/*.{html,js}'],
theme: {
extend: {
fontFamily: {
sans: ['Lato', ...defaultTheme.fontFamily.sans],
},
screens: {
xxl: '1410px',
},
},
},
variants: {
borderWidth: ['responsive', 'hover'],
},
plugins: [
require('@tailwindcss/forms', {
strategy: 'base', // only generate global styles
// strategy: 'class', // only generate classes
}),
],
content: ['./src/**/*.{html,js}'],
theme: {
extend: {
fontFamily: {
sans: ['Lato', ...defaultTheme.fontFamily.sans],
},
screens: {
xxl: '1410px',
},
},
},
variants: {
borderWidth: ['responsive', 'hover'],
},
plugins: [
require('@tailwindcss/forms', {
strategy: 'base', // only generate global styles
// strategy: 'class', // only generate classes
}),
],
};
36 changes: 18 additions & 18 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');

const production = process.env.NODE_ENV === 'production';

const OUTPUT_PATH = path.resolve('dist');

const config = {
output: {
path: OUTPUT_PATH,
path: path.resolve('dist'),
chunkFilename: '[name].[chunkhash:4].js',
clean: true, // clean the 'dist' directory before build
},
Expand Down Expand Up @@ -36,16 +34,16 @@ const config = {
},
devServer: {
static: {
directory: OUTPUT_PATH, // must be the same as output.path
directory: path.join(__dirname, 'dist'), // must be the same as output.path
},
watchFiles: {
paths: ['src/**/*.*'],
},
compress: true,
port: 8888,
},
devtool: production ? 'hidden-source-map' : 'inline-source-map',
watchOptions: {
aggregateTimeout: 300,
aggregateTimeout: 200,
},
plugins: [
new HtmlBundlerPlugin({
Expand All @@ -54,28 +52,30 @@ const config = {
index: 'src/index.html', // => dist/index.html (key is output filename w/o '.html')
},
js: {
inline: true,
filename: 'js/[name].[contenthash:4].js',
inline: production, // inline JS for production mode, extract JS file for development mode
},
css: {
inline: true,
filename: 'css/[name].[contenthash:4].css',
inline: production, // inline CSS for production mode, extract CSS file for development mode
},
minify: production, // minify html
minify: 'auto',
}),
],
mode: production ? 'production' : 'development',
stats: production ? 'normal' : 'minimal',
};

if (production) {
config.optimization = {
minimize: production,
minimizer: [
new EsbuildPlugin({
target: 'es2015',
css: true,
}),
],
};
config.optimization = {
minimize: production,
minimizer: [
new EsbuildPlugin({
target: 'es2015',
css: true,
}),
],
};
}

module.exports = config;

0 comments on commit d488282

Please sign in to comment.