Avoid duplicate Webpack chunk - javascript

I'm trying to inject into the Webpack project, and am faced with the following situation. I have two entry points: about and feedback.
about imports feedback, while both about and feedback are connected to the page. As a result, the code from feedback is duplicated twice.
Question: How can I import feedback into about without including code? That is, to make Webpack import a module from another file.
I know about optimization.splitChunks. In my situation it does not fit. The fact is that I may have many components that are connected on different pages (Maybe several at once). Combining them into one chunk and connecting everywhere is not desirable.

You need to add an additional option called optimization in your webpack config file
module.exports = {
...
optimization: {
mergeDuplicateChunks: false,
}
...
}
Please find the documentation regarding the same here - https://webpack.js.org/configuration/optimization/#optimizationmergeduplicatechunks

Related

How to get entry file raw source code before creating modules in Webpack Plugin API

Question
I'm trying to inject code into a specific entry point before webpack creates modules out of it. This code is generated in node before the bundle is created. Here are the specifics:
I don't want to manipulate the entry file, but rather manipulate the raw source in memory before webpack does its magic.
I also need to pass options in from somewhere.
Stuff I've tried
=> Create a loader
This is by far the easiest way to do it. Import a file that's targeted in the webpack config, and have the loader do the injecting. Example:
{
test: /\.custom-file$/,
use: {
loader: 'my-loader',
options: {},
},
}
The problem with this is that I'd need to have an arbitrary file (.custom-file) laying around in my repo with nothing in it, just so webpack has something to import...
You could import "nothing" by using the inline loader syntax and purposefully leaving out a file to import:
import myContent from '!my-loader';
This works, but it requires you to write your entire config inline as well. The config I would need is a bit too verbose to use this method...
=> Create a plugin
After reading (what seemed to be) all of the plugin tutorials on the internet, I'm convinced that there's gotta be a way to use a plugin to gain access to the entry file source code.
I feel like i've checked every hook and the closest I can get is the normalModuleFactory, but looking through that output, I can't seem to find the source of the entry files...
ended up using this webpack plugin:
https://github.com/adierkens/webpack-inject-plugin
the plugin creates a webpack loader on the fly and injects your code into the entry files you specify.

Common boilerplate for multiple entry points in Webpack

In Webpack (4) are there ways to pass export(s) of a given entry file into a helper module, which itself acts as entry? Basically a way to "wrap" entry points.
Now, I know I can easily use CommonChunks to import into an entry, but what I trying to do is export from the entry for another module to actually do something in its place. Here's why.
I have a react application which I'm using Webpack to build. I am porting from a NEXT.js stack which, for my purposes, is a source of overhead. One feature I want to keep though, is putting routes in a pages/ folder where I export default Component in each page, rendering automagically. This would be very nice behavior to have for a Webpack project.
Right now, I get my directory-based-multiple-entry roughly like this.
/* webpack.config.js */
const pages = {};
for(let route of fs.readdirSync('./pages')){
pages[route] = path.resolve('./pages', route);
}
module.exports = {
entry: pages,
/* ... */
}
It works; but I do need to require and setup ReactDOM.render for every entry. Alone this is not a big deal, but when getting into HMR (hot-reloading) and other things, it adds a lot of redundancy. It also makes it harder to keep my code dev/production agnostic.
What I'd like to do is this. Have one module somewhere in my project which does the actual rendering of my pages, something like:
/* init.js */
const MyEntryPoint = require("🤷‍♂️").default;
const intoContainer =
document.body.appendChild(document.createElement("div"))
ReactDOM.render(MyEntryPoint, intoContainer);
with my multiple entry pages looking like
/* pages/login/index.js */
export default () => (
<div>Welcome to the login page!</div>
)
I know there is a way to pass an array for given entries, but to my understanding they are concatenated and cannot import one another. My only other theory is to export each page as a library and manually include bootstrap code as a script-tag.
Is there any better way to do this?
I did actually figure this out at some point. Ended up rolling my own solution called
Webpack Intermediate Entry.
What it does is load a given insert file, specified in IntermediateEntryPlugin.
You can install and import this plugin via NPM as webpack-intermediate-entry.
It then replaces all entries with that file, and replacing "__webpack_entry__" import, with each in-turn.
Hopefully it helps!

How do I properly include JS libraries using Webpack?

I am quite new to Webpack and I am using it to bundle the assets used for a static website I am creating. This website uses multiple JS files from npm packages like
fullpage.js and parallax.js. I need to know how I can include these JS files using Webpack.
What I have tried
The first option I tried was import JS files via app.js
app.js
import './style.css';
import '../node_modules/fullpage.js/dist/jquery.fullpage.css';
window.$ = require('jquery');
window.$ = require('fullpage.js');
window.$ = require('parallax-js');
require('./index.js');
index.js
var scene = document.getElementById('scene');
var parallaxInstance = new Parallax(scene,{
frictionX: 0.1,
frictionY: 0.1
});
$(document).ready(function() {
$('#fullpage').fullpage({
recordHistory: false,
scrollBar: true,
});
});
However, since parallax-js is not imported in index.js, this doesn't work. Chrome debugger says that Parallax is not defined -- index.js
I can overcome this by moving the require section to the index.js but that doesn't seem clean.
My second option was to import these via webpack.config.js which seems to me is the correct approach.
webpack.config.js
module.exports = {
entry: {
main: './src/app.js',
libs: [
'./node_modules/parallax-js/dist/parallax.js',
'./node_modules/fullpage.js/dist/jquery.fullpage.js'
]
}
}
I included both the above created JS files (libs.js and main.js).
However I am still getting Parallax is not defined -- index.js
Which of the above two methods are correct? Is there a better way to achieve this?
I've read through a lot of documentation and articles but I could not find a proper answer for this very basic question which is why I am posting this here, wondering if I am missing something big.
Thank You.
Yep, you're missing something conceptually. You're still trying to use the global context (& window object). Webpack doesn't want you to work that way. Webpack wraps everything up and puts everything in modules.
You need to define your dependencies in every file you use them in. Then, you let webpack figure out how to bundle everything together. It's actually not messy to define dependencies per file; it's the right way of doing things, and the way every other programming language does it.
I would also recommend switching from require syntax to import syntax, as it helps you to think of it as a declaration, not a function call.
It might be helpful to poke around an ES6 tutorial/project to learn the new syntax and approach. It's a fairly major shift, and particularly difficult for existing JS developers who aren't drawing from experiences in other languages.
You may find this tutorial (or others) helpful: https://www.youtube.com/watch?v=lziuNMk_8eQ

WebPack sourcemaps confusing (duplicated files)

I decided to try out WebPack on a new project I'm spinning up today and I'm getting really strange behavior from the sourcemaps. I can't find anything about it in the documentation, nor can I find anyone else having this issue when skimming StackOverflow.
I'm currently looking at the HelloWorld app produced by Vue-CLI's WebPack template -- no changes have been made to the code, the build environment, or anything.
I installed everything and ran it like so:
vue init webpack test && cd test && npm install && npm run dev
Looking at my sourcemaps, I see the following:
This is a hot mess. Why are there three version of HelloWorld.vue and App.vue? Worse yet, each version has a slightly different version of the code and none of them match the original source. The HellowWorld.vue sitting in the root directory does match the original source, but what's it doing down there instead of in the ./src/components folder? Finally, why isn't there a fourth App.vue that has the original source for it?
As far as I can tell this may have something to do with the WebPack loaders. I've never gotten these kinds of issues with any other bundler, though. Below is an example of the exact same steps using the Browserify Vue-CLI template:
No webpack:// schema, only one copy of every file, the files actually contain the original source code (kind of important for source maps), no unexpected (webpack)/buildin or (webpack)-hot-middleware, no . subdirectory,.... just the source code.
I haven't worked with Vue so can't really describe how exactly this is happening but it seems to be related to Vue Loader. Looking at the documentation I did not really find anything that clarifies why it would create three different files for one component. But it does seem logical considering that a .vue file might contain three types of top-level language blocks: <template>, <script>, and <style>.
Also, looking at two of those files you do see a comment at end of each file that suggests it was modified in some way by a Vue loader. Either this
//////////////////
// WEBPACK FOOTER
// ./node_modules/vue-loader/lib/template-compiler
or
//////////////////
// WEBPACK FOOTER
// ./node_modules/vue-style-loader!./node_modules/css-loader
The third file is different but it still does have code that identifies it as being modified by Vue loader. Here is some of that code
function injectStyle (ssrContext) {
if (disposed) return
require("!!vue-style-loader...")
}
/* script */
import __vue_script__ from "!!babel-loader!../../node_modules/vue-loader/..."
/* template */
import __vue_template__ from "!!../../node_modules/vue-loader/..."
/* styles */
var __vue_styles__ = injectStyle
The document also says this:
vue-loader is a loader for Webpack that can transform Vue components written in the following format into a plain JavaScript module:
Which explains why you might not see the same type of behaviour with other bundlers.
Now, This might not be the answer you were looking for but just wanted to share what I had found.
This is actually a feature of webpack.
webpack has HMR (Hot Module Reloading). If you look in your network tab, go ahead and make an update to your HelloWorld.vue file. You'll see a js chunk come thru as well as an updated JSON manifest. Both of these will have a unique hash at the end for each time you make a change to the application. It does this so the browser does not have to do a full reload.
For a better explanation of this I would highly recommend reading through https://webpack.js.org/concepts/hot-module-replacement/

Js with git handle control version with the new module system client side

I see that the world change and everybody include my self is working with module system like common js in the client side.
In all the tutorials and blog posts i see the method is to have one file that we import all the other files to him.
So for example my project is written in angular js and the files looks like this:
//about/index.js
import AboutController from './aboutController.js';
import aboutDirective from './aboutDirective.js';
export default (app) => {
app.controller('AboutController', AboutController);
app.directive('about', aboutDirective);
}
//Main.js:
import modules from './modules';
const app = angular.module('name', modules);
import About from './components/about';
About(app);
So every feature will be added to this file and will pass the app to it.
My question is when every person in my team works on other feature and added this feature to this Main.js file, we will always get conflicts when push this code to git.
What is the solution to this approach?
I think your question is more about git then javascript. But me and my colleagues use this workflow to prevent/solve the conflict:
1) commit: first of all commit you modify so you cannot lose that.
2) Sync your project: by a fetch you see the difference and the conflicts
3) Resolve the conflict: we resolve the conflict manually, when you have resolve it, and you have choose the mod to keep or discard you make another commit. If you decide to take all the repos modifies you can "add to index" your file changed, then you commit again.
We always resolve the conflicts in that way, how to prevent it? you will have a conflict in the moments that someone modify your same file and:
1) the same rows: there is no way you don't have to follow the workflow above
2) not the same rows: in this case, if you have commit before the fetch you'll not have.
hope be of somekind of help.

Categories