Integrating webpack into my WordPress workflow - Separate but related questions - javascript

This may be a bit of a long-winded one, but I am looking to use webpack going forward and can definitely see some advantages. However, some of the concepts are a little different to what I have been used to coming from a PHP-based environment and using Gulp.
There are a few things I am trying to get my head around so to help those interested with the post, I have highlighted my questions or what I am looking to achieve.
Background
I am building a boilerplate theme that has the usual WP files.
style.css
functions.php
sass
js
...
Amongst those files I have a directory called gutenberg. In this directory, I have a number of custom blocks (made using the #create-block package and ES5 syntax) that I am looking to package up similar to a React component. Each custom block folder contains:
{blockName}.php
index.js
style.scss
editor.scss
utils-{blockName}.module.js
What I am looking to do is generate a bundle.js file, but create separate files for each block so they can be imported on-demand in an attempt to reduce the initial bundle size. Ideally, this would be separate JS functions and CSS files.
What I have achieved so far
Working through the Webpack documentation I have managed to get a basic implementation going, but everything seems to compile into one and I am looking for a bit more control/chunking, and obviously my current output does not take advantage of Webpack. I can then import the required scripts (hopefully using an Intersection Observer) when a block starts to come into view. However, I'm not even sure this is possible. This is just my mind thinking what might be possible.
My deps are:
"dependencies": {
"#splidejs/splide": "^4.0.6"
},
"devDependencies": {
"#babel/core": "^7.18.2",
"#babel/preset-env": "^7.18.2",
"babel-loader": "^8.2.5",
"css-loader": "^6.7.1",
"mini-css-extract-plugin": "^2.6.0",
"sass": "^1.52.2",
"sass-loader": "^13.0.0",
"style-loader": "^3.3.1",
"webpack": "^5.73.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.9.2"
},
My webpack config currently looks like this:
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const entryPoints = {
app: "/js/app.js",
style: "/sass/main.scss",
editorStyle: "/sass/editor-styles.scss",
};
module.exports = {
entry: entryPoints,
devtool: "inline-source-map",
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].js",
clean: true,
},
mode: "development",
devtool: "inline-source-map",
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
}),
],
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"],
},
},
},
{
test: /\.s?[c]ss$/i,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
],
},
};
and creates a dist similar or identical to this:
app.css
app.js
editorStyle.css
editorStyle.js
style.css
style.js
Now, the files that I am actually loading in are app.js, for my bundle. editorStyle.css for the styles in the editor, and style.css for the front-end styles. So am I right in saying I don't need app.css, editorStyle.js, and style.js? If so, how can I removed these from the build?
An attempt at code splitting
I did have a go at code splitting and got a result, but wasn't sure how I then use that chunk. I'm very new to ESM and have come from the standard one-long-js-file.js way of doing things
I have two blocks that use the same library, SplideJS. In those blocks utils-{blockName}.module.js I import Splide using the following method:
import Splide from '#splidejs/splide';
import '#splidejs/splide/css/core';
...exported functions...
In my webpack config I included the following:
optimization: {
splitChunks: {
chunks: 'all',
},
},
Which created a chunk file along the lines of vendor_splide-....-...-...{hash}.js. When I have a chunk like this, can I conditionally import it? The naming convention is obviously a standard method, can I have any control over how these chunks are named?
Bundling
One thing I did come across was the size of the bundle once Splide was imported. Jumping from 8kb to around 70kb in development, and over 80kb in production. Splide claims their package is around the 30-40kb size so I wondered was I importing it multiple times. I read that including source maps is expensive and removed devtool: "inline-source-map" from my config but it actually increased the bundle size, only slightly. Is it common for there to be discrepancies in claimed dist sizes of packages, or am I importing the library incorrectly (based on my above import statements)?
Any help with integrating or answering some of my early questions would be greatly appreciated.

Related

How to speed up Vue.js command line processes and optimize a webpack build

I have a very simple tutorial project that I built which consists of no more than 100-200 lines of code.
When I build this project with webpack I end up with a bundle.js file which is being flagged as being above the recommended size of a bundle.js file. I find this unsettling because I know that my code is very small. How is it that with only using a few things like vuex, vue.js and a few node modules ending up with such an oversized bundle.js?
I understand that it packages everything up for us, but I find it hard to believe that with such a small project webpack would be unable to get it down to a much smaller size. I am concerned that this might have something to do with the sheer number of node modules I have in that project root directory.
So my question is this: does the webpack build depend at all on what node-modules are in my directory under the /node_modules/ folder? If not, then how have I already exceeded the recommended size for a bundle.js with my first ever vue project?
This brings me to another question which I have been very unsure of: Is it normal for vue to copy over almost my entire node_modules directory from my root user directory? When I watch tutorials, the "vue create My_App" command seems to finish executing in no more than 10-20 seconds, but when I run the command it can take minutes. When I was wondering what it could be I saw that it copied hundreds and hundreds of node_modules over... is that entirely necessary? Is there a configuration or setting I should have set or changed that I missed?
Thank you all for any insight you might be willing to offer, big or small.
// webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const path = require('path');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/dist/'
},
mode: 'development',
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
// this will apply to both plain `.js` files
// AND `<script>` blocks in `.vue` files
{
test: /\.js$/,
loader: 'babel-loader'
},
// this will apply to both plain `.css` files
// AND `<style>` blocks in `.vue` files
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.common.js'
}
},
plugins: [
// make sure to include the plugin for the magic
new VueLoaderPlugin(),
],
optimization: {
minimizer: [new UglifyJsPlugin()],
},
};
Use tools like https://nx.dev/
You can find video here https://youtu.be/mVKMse-gFBI

javascript + gulp + babel + webpack. error: Module not found: Error: Can't resolve 'babel-loader'

I'm creating a javascript project. To create it I'm using gulp and babel.
My problem is that I can't develop my code over multiple file, so I'm search a solution to 'enable' importing. At the moment I'm trying to configure webpack.
The Gulp Task is this:
gulp.task('webpack', () => {
return webpack_stream(webpack_config)
.pipe(rename('webpack_code.js'))
.pipe(gulp.dest('.build/asset/webpack/'));
});
The webpack.config.js is this:
module.exports = {
entry: ['./src/asset/js/main.js'],
output: {
filename: 'bundle.js',
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.(js)$/,
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
presets: [
['env', 'stage-0',{ modules: false }],
],
},
},
],
},
resolveLoader: {
modules: ['./node_modules'],
},
resolve: {
modules: ['./node_modules'],
},
target: 'node',
};
My current error is this:
Error in plugin 'webpack-stream'
Message:
multi ./src/asset/js/main.js
Module not found: Error: Can't resolve 'babel-loader' in ...
What's wrong?
Another Question: What's I have to put as value of entry key? Only the entry point js file or the whole files of the project?
Thanks!!
What's wrong?
I'd guess that in your project, your Webpack instance is not finding the babel loader because of your config / environment specific issues.
I've had the exact same issue as you. Here are some troubleshooting steps for to check first:
See if babel-loader is actually installed. I know it is simple, but it can save you time.
Check which Webpack/Babel versions you're dealling with in your package.json file. I'm using Webpack 4 and Babel 8. Sounds like some newer versions doesn't accept this: use: 'babel' in your webpack.config file. You need to ensure that the -loader is being used as it follows: use: 'babel-loader'.
Reinstall your node_modules folder. Sometimes it works.
Another Question:
What's I have to put as value of entry key?
Only the entry point js file or the whole files of the project?
Accordingly to Webpack's docs:
The entry object is where webpack looks to start building the bundle. The context is an absolute string to the directory that contains the entry files. - Webpack Ref
Considering that, you should pass to the entry object, the path of a folder or a file that will be used to generate your final JS file with all your modules in it.
If you have nested files, that you don't import as modules, I think you'll have to head to the docs and see this specific case.
But if this files are nested and are being imported as modules, in your entry file/folder, they will be generated in the output file.
I know it's not much but following these steps, helped me to solve it. :)

Webpack CSS Modules Not Loading New Code

I'm having a very weird issue where any new CSS files I create and import in my JS code do not get added to the output file. My webpack config is set up to bundle all CSS files required in my React components into one output file called styles.css. Here are the relevant parts of my config:
module.exports = {
...
module: {
rules: [
...
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader?modules=true&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'],
})
},
...
],
},
...
plugins: [
...
new ExtractTextPlugin('css/styles.css'),
...
],
};
This config creates a file called styles.css and puts it in a directory called css in my output directory.
Heres the weird part: It currently generates the hashed class names for all of the files that are imported in my code, but it ignores the class definitions of some files (on a consistent basis).
I was using these versions of the packages:
"css-loader": "^0.28.4",
"postcss-loader": "^2.0.6",
"style-loader": "^0.18.2",
"webpack": "^2.6.1",
I even tried updating all of the packages, but the problem persisted.
I tried running webpack on three different machines, in both production and development mode, and always get the same results.
Any ideas? Am I missing anything here?
I actually found an answer: I was using chunks as separate entry points in my webpack, but was (quite carelessly) rewriting the same CSS file without regard to the different needs of the different entry points. Until now, I had mostly the same CSS rules for all of my entry chunks, which is why I didn't see this before.
D'oh!

Consistently very large bundle for vendor -- what should be done to reduce it?

I am bundling my vendor dependencies like so:
module.exports = {
entry: {
vendor: [
'react',
'react-dom',
'react-router',
'velocity-react',
],
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: Infinity,
filename: 'vendor.js',
}),
]
}
Despite these few dependencies, webpack is consistently saying that my vendor chunk is large.
I am not so sure that this is being handled correctly -- is there a way to reduce this bundle's size? Should dependencies such as react be broken into their own separate chunk?
What we usually do is to mark the external libraries as "externals" in our webpack - this keeps our core library independent of the third party dependencies. Here is an example :
https://github.com/flexicious/react-redux-datagrid/blob/master/config/webpack.config.js
webpackConfig.externals = {
"react": "React",
"react-dom": "ReactDOM",
"flexicious-react-datagrid":"flexiciousNmsp"
}
You should generate your bundles with minification enabled (basically running webpack -p for production).
In addition, you should set the global variable process.env.NODE_ENV to production so the dead code elimination works within the React module. See here:
http://survivejs.com/webpack/optimizing-build/setting-environment-variables/#setting-process-env-node_env-
If you finally enable gzip compression on your webserver it should go much lower.
For example, see here the CDN version of the latest React, minified:
https://unpkg.com/react#15.4.2/dist/react.min.js
https://unpkg.com/react-dom#15.4.2/dist/react-dom.min.js
Open your browser Dev tools, networks inspector, and see they are at around ~30Kb each (gzipped).

Using Webpack and stylus to create static css

new to Webpack. I was thinking about migrating JS part of my application to it. However, I don't like the way it handles CSS. Would like to keep it easy and link them on my own. Unfurtunately documentation wasn't very helpful, same with the search results.
So, what do I need exactly?
Stylus compilation from lots of .styl files to static .css.
There will be three static stylesheet files (entry points?), but completely different from entry points of JS part of an application.
Also some "watch" feature, which would compile css when one of source .styl files has been changed.
Is there somebody who could point me in right direction, maybe write a config? Is this even possible with Webpack or should I stay with Grunt?
Thanks for any useful answer.
To learn more about the details of Webpack you can refer to this online book SurviveJS - Webpack, which will walk you through most of concepts related to Webpack.
To accomplish what you need you can start by creating webpack.config.js in the root of your project and it can be like this:
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: './entry.js', // you application entry point
output: {
filename: 'bundle.js', // resulting bundle file
path: './public' // the output folder path
},
module: {
loaders: [
{
test: /\.styl$/,
loader: ExtractTextPlugin.extract("style", "!css!stylus") // plugin used to extract css file from your compiled `styl` files
}
]
},
plugins: [
new ExtractTextPlugin('style.css') // output css bundle
]
};
Then require your stylus files in you entry.js file require('./style.styl');
Don't forget to install required loaders and plugins
npm install --save-dev css-loader sass-loader style-loader extract-text-webpack-plugin

Categories

Resources