The biggest reason appears to be that Webpack 4 is essentially a completely botched release. There are docs on there that still have not been updated for Webpack 4.
A good example is caching, https://webpack.js.org/guides/caching/, is still about Webpack 3 and not about Webpack 4. Another one is that the replacement for extract-text doesn't support HMR, so you have to use something else in dev mode.
Great article! Really clean and to the point.
A thought:
> Whenever it’s possible, I’d recommend to use dynamic imports to import components.
I would say it's probably not better to use this technique whenever possible.
After using code-splitting with webpack in a medium-large sized project, tweaking the chunk sizes and such, I've come to the conclusion that you should only use dynamic imports at the route definition level. If you do that, then you can use webpack hints to name the chunks meaningfully. It's hard to find in that documentation link, but this is the important line:
return import(/* webpackChunkName: "lodash" */ 'lodash')
or rather
const SomeComponent = import(/* webpackChunkName: "some-component" */ ./some/path/component.vue)
I've noticed that if using micro-chunks, even though webpack does a good job chunking every single import out during the build process, at runtime the website load time is slightly higher than using slightly bigger macro-chunks. I tweaked webpack chunk settings for a few hours to find that minimum 30-32Kb and maximum 64-96Kb gives the best results (webpack will automatically create common chunks for reused code between chunks). Your mileage may vary.
Happy coding!
The main webpage and documentation have been rewritten for webpack 2, it's gotten quite good. https://webpack.js.org/guides/
Pick a guide, "getting started" and "creating a bundle" will teach you everything to get going, make a first build and use it. You extend your config every once in a while, when you need something extra, be it a new loader, maybe for css or image compression, babel and so on.
> Ah shit, i can't write a decent function to output time in a human-readable format (wtf?!), better use some bloated library
It's silly to pick apart a simple example to show how stupid all the tools are. Of course you could format a date without a library, but the moment library handles almost anything with time. Also, native Javascript dates suck, that's why the moment.js library gets 12 million downloads every month: https://www.npmjs.com/package/moment
> And because of that i'll also throw a library package manager into the mix, because i can't be bothered to keep that updated myself.
So if you're manually updating packages, how you keep dependencies in sync across a team of developers? When you upgrade the package from v1 to v2, do you just send an e-mail, and the other devs have to go manually upgrade it? How does that work when deploying to prod? Do you commit the entire node_modules folder to source code?
> the npm folder gets fucking large because of all those dependencies i have, what about users concerned about bandwidth or low end PCs?
Webpack has tree shaking, which eliminates dead code from that "fucking large" npm folder: https://webpack.js.org/guides/tree-shaking/
> who cares about page display speed or a few dozen megs of RAM used by all this shared library code
I'm not even using tree shaking on a site with 9 shared libraries and the compiled JS file is 800 KB. Not dozens of megs.
> But on the other hand i see jQuerys syntax abdomination and just think "Why?"
Jquery was created years before NPM, Webpack and the rest. It's an ancient relic of Javascript. Most people who use Webpack and NPM are using React/Angular something similar.
I agree that if your users are confused then it would be worthwhile to improve docs, but I think Webpack's docs are actually pretty good over at webpack.js.org.
My only issue with Webpack is when the extensions/modules/whatever they're called don't have good docs. But that isn't Webpacks fault directly, it's the extension-whatever's creator's fault.
It looks like you need to add libraryTarget: “umd” to the build option in your webpack config. By default webpack tries to expose your library via a variable, which is why trying to load it as a module won’t work.
Look at https://webpack.js.org/ and https://github.com/webpack/webpack
See all the company logos? Webpack is great for sure, but why does it attract so many sponsors? There's loads of other great projects not receiving a dime despite having Patreon pages or whatever.
It's the logos (and links) themselves! Because by putting my logo on your Github and project page, I can both mentally and practically claim it as a marketing expense. Marketing being an established bucket of money you can use for things that increase your company's visibility.
But if you simply offer a donation system, or feel-good sponsorship, how would I even classify that? Sounds complicated from a business point of view. Even a support contract is a harder sell than just pure marketing.
Heck, if I know my customers are using projects X and Y, I'm willing to pay just to put my logo in front of those users even if we as a company are not using X and Y ourselves! And by payment, I don't mean a $50 one-time donation, companies are willing to pay $X00-$X0000 per month for that kind of targeted exposure. And if you do this for your project, please note that companies value direct links to their chosen landing page much more than to some generic "sponsorship aggregator" page for the company.
It isn't related to Typescript, but to Webpack. Hot module reloading is undecidable in general and you have to write code to cover edge cases. https://webpack.js.org/concepts/hot-module-replacement/
https://webpack.js.org/guides/hot-module-replacement/#gotchas
Honestly it's not that bad. If you are looking to refactor it I would recommend taking a look at date-fns. The Date
object in JS is actually not that bad, but it's interface is a bit low level and pretty cumbersome to use, especially for formatting (as shown in your code). date-fns
is a collection of mostly wrappers around the Date object to make it easier to use, it is also really friendly for tree-shaking so its pretty light-weight in practice.
Here is my take on this code (using date-fns):
import { format } from 'date-fns'
const byId = id => document.getElementById(id)
function numberedTime(now = new Date()) { byId('time').textContent = format(now, 'HH:mm:ss:SSS') byId('date').textContent = format(now, 'dd/MM/yyyy') }
function labeledTime(now = new Date()) { byId('label').textContent = format(now, "'It is' EEEE, 'the' do 'of' MMMM") }
const waitForAnimationFrame = () => new Promise((resolve) => window.requestAnimationFrame(resolve))
const startUpdating = async () => { while (true) { // doesn't actually block the main thread because it contains an await await waitForAnimationFrame() // Update every frame instead of every millisecond numberedTime() labeledTime() } }
startUpdating()
byId('back').addEventListener('click', () => { // .assign() is easier to mock than .href, also more consistent with .replace() window.location.assign('../index.html') })
Import one library and see what happens. Webpack is doing a lot more than just resolving modules by now.
For example: Import lodash
and use one function. With the old approach the whole library would be loaded (just like the good old jQuery days). Webpack will analyze your code and just include the function you really need. This will dramatically reduce the size of your bundle. Just try it out. + Look through their guide. You will find things like Tree Shaking, Code Splitting or the webpack-dev-server. These things will optimize your development workflow and also result in a smaller production script so everyone with a bad connection is happy :)
Also webpack bootstrap code is there to enable an easy use of the module system. Look through this blog post to understand there are different module types. And for example you are using import, export (ECMAScript Modules) which are just supported with special flags in the browser. So webpack has to change the modules to something the browser javascript engine can interpret. Otherwise it would just fail.
We faced months ago the same problem in my company, however we took different choices For instance, instead of awesome-typescript-loader we went for ts-loader since, imo, it has better support, for making it work alongside Babel we just take the output of ts-loader and send it to Babel-loader (https://stackoverflow.com/a/38321269) Moreover in out tsconfig we have set module and target to es6 and in our Babel config, for the preset-env, we have set modules to false That way the tree shaking of webpack is able to show a better performance (https://webpack.js.org/guides/tree-shaking/) Hope some of these tips can help!
Nice fairly high-level overview (EDIT: in the first part of the article). I'm bookmarking for when I need to explain Webpack to non-tech folks!
I think the section about setting the env flag at the end may be outdated?
E.g. instead of setting NODE_ENV directly:
NODE_ENV='production' webpack
Now it's recommended to pass in a flag:
webpack --mode=production
What are you using to compile the SCSS? I know that Webpack, for example, has several different "presets" for creating sourcemaps, each with it's own pros/cons. You can see the chart detailing the presets here
You should definitely be using the WordPress-bundled jQuery. There is a very high likelihood of you installing plugins that also depend on it. If you bundle your own, you'll end up loading jQuery twice. You could tell WordPress to use a CDN or something for its version, and incompatibilities will likely be slim-to-none, but the WordPress-bundled copy offers the least risk.
​
And you can actually configure Webpack to consider that a library, like jQuery, was loaded outside your bundled scripts and should be available. It's called externals.
Love listening to Antonio's talks, and I've had a great experience introducing Clojure into our JavaScript stack by way of Lumo. One thing I didn't understand during this talk, however, is the claim that bundle splitting is weirdly magical in webpack land.
The point about special/magical comments is only slightly true; they can be used to name chunks, but for all practical purposes are entirely unnecessary[1]. We leverage bundle splitting quite heavily on our React application, and it's honestly a breeze. Webpack is smart enough to notice split points defined by dynamic import()
calls, and that's it, you're done. That ultimately frees you up from static configurations, which only become necessary for your primary entry point and static vendor bundle.
Looking at the ClojureScript way, it's still an improvement on how things were done (in CLJS) previously, but I struggle to see how it's objectively better than what's available in the larger ecosystem. Now, of course I absolutely adore Clojure and ClojureScript (I'm at the Conj, after all), and am pushing to work the latter further into our stack, but this claim seemed a bit hand-wavy.
I realize there is a permeating hatred of webpack and JavaScript tooling, but I do legitimately think there are some things that the community does quite well, and those things shouldn't be discounted just because of the stack. If ClojureScript does them better, awesome! I'm sure such rationale exists, but it is difficult to drill into such detail during a quick talk.
So, if I'm completely misguided here, I'd appreciate it somebody could help me understand the issue more clearly. There are of course great benefits to be had with the new module integration, such as Google Closure optimization, but this one point in particular stuck with me.
Webpack is at its most basic a module bundler. That is, it allows you to import
or require
different files, and Webpack will then bundle them all up and serve them as a single file (that browsers understand).
What Webpack does depends on what file you're importing and what you've configured it to do. Webpack uses "loaders" which your file is run through (you can see a list of some of the official ones here).
You might want Bob to check for typos (eslint-loader), Jim to turn your letters into something readable (babel-loader) or Anitta to glue in pictures (file-loader). It's really up to you.
There are many, many other things you can do - hot module reloading, code splitting, async import, so on and so forth. An important thing to remember is that all your code is bundled into a JS file - this brings some advantages, but also a lot of disadvantages. For this reason Webpack might not be ideal for your project.
docs are getting really nice I'd say yes. I mean it is complex as the thing you want to do is complex. but for me it's quite easy to set up the basic stuff ( minify, source map, etc ) and set up a web server w/ hot reloading for my projects which were kind of a pain (imo) using gulp/grunt
Cli's are great for getting things up and running if you have never worked with Webpack before, but the moment you need to adapt them to your needs you're in trouble. To be fair, Webpack has come a long way since version 1. The latest Webpack has a pretty good documentation and configs are trivial:
import webpack from 'webpack';
export default const config = { entry: './index.js', output: { filename: 'bundle.js', path: './dist' }, module: { rules: [ { test: /.(js|jsx)$/, use: 'babel-loader' } ] }, plugins: [ new webpack.optimize.UglifyJsPlugin() ] };
WP doesn't 'have it's own javscript' on the front end. Sure, there is some admin stuff included when you're logged in but I don't really count that. Your theme will have it's own javascript and that will almost certainly include jQuery. Themes handle javascript in different ways.
If you're not compiling your JS with a tool like Rollup or Webpack, the 'npm install' method won't work.
There is a guide on the cesium website on how you can include the bundle from a CDN and bypass compilers / bundlers all together and is what I would use if I were trying to integrate it into a WP theme.
https://cesium.com/learn/cesiumjs-learn/cesiumjs-quickstart/
The div
<div id="cesiumContainer"></div> is where it would render. The guide seems to assume some basic javascript knowledge.
I wouldn't use the standard wp_enqueue method for this unless you know what you're doing and know how to only include it on the pages you are going to use it on. The above tutorial should get you pretty close to where you are trying to go.
These bundlers can be very helpful because they are helping with :
tree shaking : they can remove files that are not used like some css files
Code splitting : they split the files that are send and you can load files only on demand
code minimisation, optimisation, etc...
However, you can still have issues with the bundlers themselves because they need to be configured the right way. They are not a magical solution.
Check this link about optimizing LCP => https://www.marfeel.com/resources/blog/speed-up-largest-contentful-paint
Yep, that's normal.
I don't know exactly what step it is, but I remember that is there because Angular now uses AOT compilations for every build by default and this step helps with the tree-shaking process.
The official doc have more info about this:
And don't worry, ng serve
uses ng build
but without the --prod
flag, so during development you'll see that the bundles/chunks are larger than the ones compiled for production.
> I Don’t have the time
You see, time is an incredibly valuable resource. Here you go, no source required: https://webpack.js.org/configuration/devtool/
> If I was working with mission critical technology [...]
I honestly thought you were implying that the source is superior to good documentation. Following that, integration tests are inferior to the source. Integration tests (and to a lesser degree, unit tests) demonstrate how to use something: the public API surface area. You don't need the source if you have an integration tests, because an integration test is as good as a sample app.
That used to be the case, but they've added tree-shaking recently: https://webpack.js.org/guides/tree-shaking/
I don't know the difference between named and default, but tree-shaking is definitely in there to some extent now.
At some point, you are going to need a javascript preprocessor for minification or for esnext features, you might as well use a dedicated bundler like webpack or parcel. You can write your project using es6 modules, and your build system can output a package for AMD, commonjs, traditional self-applying function ((function(){...})()
) style, or all of them simultaneously. You also get super convenient features like hot reloading and non-javascript asset handling/preprocessing as well
Yep, you pretty much got it. Webpack assumes you're trying to import a .js
or .json
file by default. You can configure that in webpack's config: https://webpack.js.org/configuration/resolve/#resolve-extensions
The general concept is pretty awesome. Seriously, good work on this.
Maintainability of the code though... Might need some work. Here are some quick items that can be optimized.
1) It Looks like html is being compiled and injected it into the element. This would be awesome if it was a separate file and used webpack to import it as a template module. That way it's manageable elsewhere. HTML-loader will help you out with this.
2) It looks like there is a general function to manage click, swipe, and keypress for each type of action (i.e. play, pause). Might want to break that out into separate modules, where each module handles its own state.
3) There isn't a framework like react, vuejs, or backbone being used so you might want to minimize the amount of DOM calls being made. For example, make an initial query to grab the play button and then passed that along to the newly created play module. query from document down to specific elements are crazy expensive.
For example, You query the playlist using "document.querySelectorAll('.playlist')", then query the playlist slide show using the document again. You already have the playlist object, just use that (e.g. playlist.querySelectorAll('.playlist__slideshow') ).
The best advice I can give is if you were to reuse this with another concept, how hard would that be? Do you have to redo the app completely? or can you reuse the views with minimal change?
>He says it isn't a bottom-up, bazaar-style project. Which it isn't.
What is truly this? Even utilities maintained by some dude are technically BDFL based.
Maybe something like webpack? But even that has a roadmap driven by [sponsors](https://webpack.js.org/vote/).
Also relevant: https://gist.github.com/richhickey/1563cddea1002958f96e7ba9519972d9
As far as i can understand you i think you can use -Webpack module federation- fot this, i am currently using this in one of my projects. This is if you want to integrate a react based application inside another react based application.
In this the application you want to federate(use inside other applications) is considered as micro frontend and can be consumed as a custom component. It has a lot of features like creating smaller chunks and sharing dependencies etc.
Here is the link to that if you find it helpful : https://webpack.js.org/concepts/module-federation/
In development, you can proxy requests from your dev server to your API server. This way, the cookie will be considered first-party and the browser will send it.
See the docs for doing this with Create React App, webpack, and I’m sure other bundlers have this too.
JS Isolation requires your JS code to be an ES module. It uses dynamic module import to load the JS instead of a <script> tag. This means that the JS bundle being created needs to include ES-style "export" statements.
Webpack 5 has experimental support for creating ES modules: https://webpack.js.org/configuration/output/#outputmodule
However, I couldn't get it to work at all using the latest version of webpack (5.11.0). Tried a bunch of different combinations of options and gave up.
Switched to using rollup (rollupjs.org) for bundling which is working great.
I read the whole thread and those early comments are wrong. If you are intending to export multiple things and you put them on one object then the engine must include all associated code just in case you access any of those keys dynamically. One person was right that you could separate each of those things in to 3 separate files then whether you import them or not will determine if they're loaded but why should you be forced to store similar functionality in separate files just in case someone doesn't use everything?
Using named exports allows the compiler to statically determine how much of a module is actually used and therefore put the rest up for dead code elimination. There was a very interesting, in depth conversation in the ECMAScript discussion board when ES modules were first suggested that covers all of this in greater detail.
If nothing else, there's a very high chance that tree-shaking is being handled by Webpack and they say that it relies on the static import structure of ES modules
It really depends on your setup, project, and what you're trying to accomplish. The first question you need to answer is: should I be using bootstrap?
Not sure? Are you concerned about bundle size? Are you using a bundler like webpack or rollup? Are you using tree shaking?
You can definitely override any style with enough specificity / !important. Is it healthy? Probably not.
Should you be importing an entire library just for a few styles that you could easily write yourself? Definitely not.
A lot of CSS libraries can feel like you're just writing inline CSS as class names (looking at you, Tailwind). But there are times when this makes sense. For example, when you have a big web app built on a front end framework like React, Vue, or even Svelte, managing all the components, css, etc can become cumbersome. It's way easier to just have a library that you can reference in the markup.
But if you are just working on an HTML page or even something like WordPress, it's always best to write as little of code as possible. So if you are overriding a library like Bootstrap, you need to ask yourself.. Should I even be using Bootstrap in the first place?
It sounds like you're trying to use modern JS on older browsers. To achieve this, you need to use polyfills -- the easiest way for me is to bundle your code via webpack (actually, I use Laravel Mix)
It would be helpful if you shared your JS :)
Since you mentioned bundling, I'm going to assume you're probably using webpack. In which case, Define Plugin could be of help here?
Essentially you'd add your entire translation file to the Define Plugin in your webpack config so that at build time the translation file is available as a global variable throughout your code. Let's say the variable is called __TRANSLATIONS__
Now in your React component, you could specify your prop to reference a path on __TRANSLATIONS__
. During build time, the value of the path reference by the prop on __TRANSLATIONS__
will be injected into your component's prop so you don't have to do anything during run time.
Yep, getting away from gemified assets is an important step. You can include yarn-managed packages in sprockets's application.js. I just place jquery at the top. None of our packs have jquery dependencies, but if you do: https://webpack.js.org/configuration/externals/ to avoid double-loading issues.
Are you me? Good company and 80% remote work but really old tech.
Request to rewrite into MVC was denied and .NET Core isn't even allowed on the corporate network yet. Webforms is here to stay on my mission-critical legacy application.
My answer was to get creative since there was no ability to ditch legacy while also having a mandate to "modernize" the UI with a richer client-side experience. Server controls and client-side in webforms is... yeah.
The resulting hodgepodge is having aspx pages as nothing but rendered views without any server-side web controls.
Repeater server controls with strongly-typed data binding sometimes handle the initial page data-bind but at least it puts me in control of the HTML that plays nicely with Bootstrap. From there, client side js handles calls to the web api controllers to perform what used to be post-backs. Partial page updates that were done with UpdatePanel server controls have all been replaced with vue.js components and client-side js.
Should I feel dirty?
If you're including scripts from a random source then it's possible to get something malicious. Browsers today, though, have lots of safety systems in place to prevent scripts from other domains from doing anything too nasty.
Modern web development uses packagers like Webpack that bundle your code with any libraries you depend on, meaning you are distributing a known good version of the libraries you depend on. Or you specify that the libraries are downloaded from known good CDNs like CloudFlare or Google.
Generally speaking, in node you use require
serverside, so it would be require('./add-content')
in your app.js file. However if you want to send this to the client I would very much recommend you use something like webpack.
In that case you would use import
for loading multiple files together, and a much more complicated require.resolve
(read up on that) for asynchronous loading.
The reason why your method is not working (it could) is that you are quite clearly specifying in your app.js file that response from the server is HTML, so when you try to get a file from the server, the server responds with your file and <!DOCTYPE html>
on top, which explains your error.
Webpack has great documentation.. I guess that for .net folks anything that visual studio doesn't do for you with a button click can be considered user unfriendly.
But I understand how you feel. Reading documentation to learn to use a tool sucks. It's like a meta-problem, your app doesn't work not because of an error in your logic, but because you don't know how to use a tool that was arbitrarily designed by some dude that decided to put the time and effort to create it.
The super ironic thing about webpack is that the core team literally has to beg for money on social media to mantain the project, despite the fact that elon-musk wannabes raising venture capital for their shitty startups love webpack a lot. I guess they don't love it enough to give something back.
I took a look at the package on GIT. This package has a ton of node dependancies, so to use it you will have to use webpack to bundle all the js files and the dependencies. The entry file is waveform-playlist.var.js, but you wont be able to use it without webpack to pull in all the dependancies and bundle it up.
To import, you would just target the actual directory rather than a specific file and webpack, once configured would do the rest.
Welcome to the world of front end, where nothing is ever easy.
This particular behavior is due to Webpack, which is the code they're using to bundle their app. Other module loaders may do it as well, but i can't say that they all do.
The documentation for how webpack does its resolution can be found here, but it won't mention index.js specifically because you can actually configure what filenames it will check for, with index.js just being one of the more common ones to include in the configuration.
Check out: https://webpack.js.org/configuration/resolve/#resolve-modules
You can add components/
to web-pack's resolve.modules
which will make web-pack search your components/
directory the same way that it searches node_modules
for modules. Then, your import becomes:
import Button from "button"; import Card from "card"; ...
> How do I easily bundle the files in the second bullet? Every time I try Googling this I get "you should use..."
Great question. I don't think Google is the best resource here, probably best to directly ask other developers, since the answer is can change surprisingly often. JavaScript is a scripting/interpreted language, but it's funny, I've used it like a compiled language in every production application I've worked on...
Anyways, to answer your question: Webpack. That is, I believe, the most popular module bundler at the moment. It allows the use of import
/ export
(recommend) or require
/ module.exports
.
I'd recommend you read through the documentation to start with. Then, when you're ready to write a small configuration file (by convention, webpack.config.js
), try googling typescript webpack loader
. I've never transpiled typescript with Webpack, but I'm fairly confident there's a loader (aka, extension) for it.
> I have specific js/css files I want to include for each template html page. I can't hardcode the file paths because ...
I don't quite understand the problem here. You should be able to reference a path relative to the domain, no? For example, using /assets/app.css
, which would resolve to my.domain.com/assets/app.css
, regardless of the page's URL.
> What's going on with the background to make this work?
Short Answer: Magic and sorcery.
Long Answer: It sounds like you've got a soup of buzzwords, but don't really understand how to put them together. Lets start off with Node.
Nodejs is a javascript runtime/engine. All it does is allows you to run Javascript on a file system instead of in a browser. It isn't a server and it isn't a language. It's just a program that interprets javascript. Just like you'd have to install PHP on your local computer if you wanted to run PHP code locally on it.
This allows for tools like Webpack. Webpack is a "module bundler" which is a fancy word for saying "this program takes your modular code (code split into logical chunks) and combines them". How it does this is a bit out of an ELI5 answer, so I'll just leave it at "magic".
I'm taking a guess and saying that you're using React-CLI to start your project and running off the local development server it creates.
As you've probably guessed, React-CLI is simply a command line program that runs in node, and uses Webpack to build its modules, and in this case, do things like hot-reloading and running a local server for you to see your changes. While you are running a "server" (what a server REALLY is would take its own ELI5), it's only local to your computer for development.
If you dig a bit deeper, there should be a "build" command that builds a "production" version of your app to be used on a real server on the Internet. When you run that, Webpack will run through its module bundling magic and spit out an html file along with a bundle.js file (or whatever you've specified) and any other assets you've included that it can handle. Those are the files you'd upload to your real server online.
Prob more of an ELI-13, but ¯\(ツ)/¯
A server response doesn't have to be based on a file. This is only common because of the way web development grew up since the 80s - via static files and CGI-based programming (Perl, PHP, etc). Many websites generate their markup completely dynamically, and most generate their markup using templates executed against dynamic data.
create-react-app uses Webpack - https://webpack.js.org/. How Webpack works is pretty complicated.
There actually is an index file - it's this one: https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/public/index.html
and you can see the JavaScript rendering the React DOM into the "#root" element of that page here: https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/src/index.js
The rest of Webpack relates to how it transpiles/combines your JavaScript, CSS, HTML, assets, etc, and loads them all up into a hot reload web server.
If you're using webpack (and probably others) then you can use dynamic imports already.
Webpack will do some magic and create additional bundles that will be requested when needed. Here's the docs if you want to read a bit more on it: https://webpack.js.org/guides/code-splitting/#dynamic-imports
I did that cycle a few times, ha, IMO it's gotten better on the doc side, either that or it just clicked on the x time around. The getting started isn't too bad https://webpack.js.org/guides/getting-started/, but I did better wrapping my head around it by looking at different boilerplates people had made with it close to what I was trying to do. Also a lot of what people do with webpack is done with plugins, and those plugins usually have both docs on webpack setup and the plugin specific apis. For example babel-loader for es6 transpiling https://github.com/babel/babel-loader. I still have some frustrating moments with it during setup, but once it's configured, you shouldn't have to touch it again.
So when you click a link and you load a page, you want to load the content of the page as well as any page that page could call (async)?
Edit: So it looks like you can pass "webpackChunkName" to the import statement so that the chunk is given a static name and not a dynamic number. ex. lodash.bundle.js
instead of just [id].bundle.js
https://webpack.js.org/guides/code-splitting/ take a look at the src/index.js portion.
you have to tell webpack that you are actually building a library, otherwise it will include the webpack runtime and try to 'start' your app instead of simply exporting a module.
https://webpack.js.org/guides/author-libraries/
https://webpack.js.org/configuration/output/#output-librarytarget
Electron relies on node_modules
and package.json
, you can just npm install webpack, react, redux and everything you need and have it spit out the distributable in the folder you need via webpack.config.js. In the project i am working on i have everything in the same repo, npm start
builds the bundles and then creates electron executables for the specified target systems.
Btw, since webpack 2 the docs and guides are fine now. They were terrible before. But i think it's possible to learn it from the site. https://webpack.js.org/ I think the trouble to make create-react-app respect the electron workflow by ejecting would be harder than creating your own config.
I (mostly) understand Webpack. This is why I’m working on a tool that hides its configuration from you. I hope you’ll find it helpful.
Webpack team is also working on new improved documentation at https://webpack.js.org/. I hope you’ll find it helpful.
I use src
and dist
because that's the convention I see most often from projects I work on at my job. This is probably reinforced by the fact that a lot of libraries/frameworks I am familiar with use these conventions for boilerplate or in their tutorials/documentation (e.g. Webpack).
I don't feel that strongly about short or long names. I think most people who have been developing for awhile are familiar with the common names either way. I wouldn't really base anything around how node_modules
get named though, since that directory name is generated automatically when using npm packages and isn't really something you configure.
https://webpack.js.org/configuration/mode/
This is insane. How does that even make any sense that process.env
is different from the process.env
in process.env.NODE_ENV
?
After changing to --mode none, process.env.NODE_ENV
logs none
. The only way to access the NODE_ENV
that defined in my .env, I have to destructure it with const { NODE_ENV } = process.env
and console logging NODE_ENV
gives me staging
.
This literally fucks with a person's understanding of objects. Where can I turn to to find answers on exactly this works? I'm seriously confused as fuck.
Hello! As you can see in resolve reference in Docs, you shouldn’t start with dot and slash in path.resolve.
Your path in output setting should be: path: path.resolve(__dirname, “build”),
How likely are the two versions to diverge?
If the extended version is built on top of the base version, it might be enough to keep it all in a single branch, and manage the version via feature flags. Eg one app version would be deployed with an env var that enables all the extra features, the other would not.
If there's still a considerable overlap in souce code, but maybe too large to be covered by feature flags, then, since you're building a website, look into how the app is built. Eg in Webpack you can have multiple "entrypoints" (main files), which allow you to build two different apps from the same source code.
And if the two versions are not compatible, you can always use version control as /u/RexTheWriter said. Using different branches for different versions is completely valid (if they're incompatible / divergent). Consider how tools maintain multiple branches for different versions, eg NodeJS
That's great!
The tree project is using a tool called Webpack - it takes un-minified assets in separate files and combines them into a single file and minifies them, among other things.You can also use Webpack yourself in your project and tell it to include the files from the tree project into your bundle.
Something to look into down the road, if you're interested! But as you saw, totally not necessary to use Webpack if you don't want to.
[Edit: forgot to include this] Here's a link to the Webpack page if you'd like to check it out. https://webpack.js.org/
No, it will not impact time to start. Angular is using webpack under the hood. Here's maybe a better explanation: https://webpack.js.org/configuration/dev-server/#devserverdisablehostcheck
The webpack dev server checks the host header to see if it aligns with the "allowedHosts" array. If the host is not present, the request is rejected.
It's secure by default, dis-allowing requests from other devices on your network, because by default, 0.0.0.0 is not an allowed host.
For sure, happy to help. You don't want to distribute the source maps with your production code that you expose to users. Source maps are developer tools to help you figure out what line in a bundle corresponds to a line in your source code so you're not getting all these wonky stacktraces that don't mean anything to you.
Similar to before, webpack has the devtool property that you can set, Next.js handles this for you as well, it's the difference of building with npm run dev
and npm run build
.
If you have all the images before hand, you can use webpack's public path feature and then just reference them relatively, so something like:
<img src={/public/${imageName}.svg
/>
Absolute paths are usually always better, it makes refactoring so much easier. However, if you're importing a file in the same directory, I think it's probably fine to have it as relative as well.
By the way, what you're describing is a webpack alias https://webpack.js.org/configuration/resolve/. You can add any symbol to point to any directory. I usually alias specific folders to make it easier, i.e @images -> root/resources/images
Webpack has an Image Minimizer Webpack Plugin (Catchy name eh?).
Gulp has gulp-image that can handle a lot of image types.
Typically folks do this in their build process, but that kind of assumes you're also doing JavaScript build stuff.
If you're trying to use environment variables for a front end asset, you should use a front end build tool like webpack or grunt. Here is a plugin for webpack that will solve your problem: https://webpack.js.org/plugins/define-plugin/
Your IDE doesn't much matter, you can use the one you are comfortable with. (The industry standard at the moment is VSCode.) What you are looking for is a local server with hot/live reloading. It's generally something that's either set up for you (such as with create-react-app) or something that you can set up yourself using Node. One popular solution is https://webpack.js.org/configuration/dev-server/
Depends what exactly npm start
does I guess. Webpack DevServer lets you set the browser in the config file: https://webpack.js.org/configuration/dev-server/#devserveropen
Create React App uses webpack DevServer, but I'm not sure how you'd override the CRA config.
When using a string src like "images/img1.jpg" no webpack rule is applied. Both file-loader and url-loader only applies to imported modules. And since no rule is applied the image isnt existing in the post process bundle.
Edit:
What you could do is to use file copy plugin instead to copy your images catalog to the dist catalog on build, and then use src string. But you will need to prepend it with the public path, and never use relative paths.
Usually you will create a folder structure similar to:
Root src public build
src contains your JavaScript
Public contains HTML and assets like images
Build is the production build of your site
Any third party stuff is usually stored in src as another folder named vendor
Inside of src you would have a folder for say a game.
game folder could look like:
root src game index.js enemy.js
This is the overall structure for a project using a bundler and npm. A good bundler like webpack can work its magic on your code base and do code splitting and tree shaking and all the other fun optimizations so you don’t have to worry about them.
You will want to have a logical folder structure that works for you and stick to it across your projects so it becomes natural to navigate through everything.
I recommend grouping similar things in a root folder and then breaking them out into their own folders if necessary.
For a small project that doesn’t use a framework. You really don’t need to worry about all the optimization stuff and usually everything can be dumped into src.
At the end of the day, it comes down to what you like. There are some industry recommendations for project structure, but you can feel free to tweak them as needed.
If you are working on a professional project you will have to abide by the folder structure implemented by the code maintainer unless you can convince them to change it, but that could be a total nightmare.
If you aren’t using a bundler and your projects are a decent size then I would learn WebPack . Heck I would learn WebPack anyways.
Yo Pussyrich, my guess would be start with Treeshaking. https://webpack.js.org/guides/tree-shaking/
It basically gets rid of stuff JS libraries etc you’re not using from what I understand. I haven’t used it on a project yet myself.
That being said a great place to start is to ensure you’re using all the libraries you’re importing. Then from there check if there’s any Netlify plug-ins that can help you. Because some of them are absolutely rad.
^^^ A better and more succinct explanation than mine. I was only using Bundler as an analogy, but yep... it does need to be stressed that Webpack is much more than just a dependency manager.
If you visit https://webpack.js.org/ you may feel a little lost at first, as it is a big system. If you focus on doing things the "Rails way" via the webpacker gem (per u/that_which_is_lain's link) it's an easier entry into webpacker in general.
Check out Lazy Loading.
I wonder if maybe loading different stylesheets based on state is not a good idea in the first place? Isn't it best to use dynamic classes here?
Well, it affects tree-shaking while bundling.
At the same time I find it very convenient sometime to access constants as a subproperties rather having long list of named imports:
import TextInput from 'lib/TextInput';
<TextInput
width={TextInput.width.SM}
type={TextInput.type.Number}
state={TextInput.state.Error}
So to me it should be decided per each instance. If it's your own component, high chances you are consuming it completely, so no difference for tree-shaking optimization. For some shared library it's in opposite typically.
Yes it is!
You need to use a module bundler, such as webpack: https://webpack.js.org/ and you need to add a postcss tool: https://postcss.org/
On my projects I use webpack + laravel mix + purgecss to remove the unsued css of my themes and plugins.
Let me know if you need any help!
Is there a particular issue you're facing, or a particular question you want to ask?
With Webpack there are loaders for Babel, SCSS, and for uglifying/minifying/obfuscating your code--you just need to:
1. configure the necessary loaders in webpack.config.js
--the entries for the loaders should give you code to copy paste.
2. Put those files somewhere in src
, and import
them in your index.js
(or whatever entry point you have configured, or somewhere else in the dependency tree where they'll eventually be reached by recursive import
).
3. Any libraries, likewise just import
in the files that use them.
You can also run webpack-dev-server
, which will serve the output and live-reload when you edit anything in the deps tree. Very convenient and intuitive.
Those require
are for Node.js (server-side JavaScript). You want client-side JavaScript. Fortunately, there are tools like Webpack and Browserify that bundle all the dependencies (the require
s) in a single file, easily included in a webpage or (in your case) a shortcut.
Have you tried running just the “no config” set up (ie using defaults values for input and output files),
then adding single explicit entry and output to see it working?
module.exports = {
entry: './src/foo.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'foo.min.js'
}
};
Looks like you are trying some config for multiple dynamic parts, mixing various formats and namings
Also, webpack as such doesn’t “minify” as such out of the box, so might want to leave the .min for when doing dev and prod versions with differing config https://webpack.js.org/ https://webpack.js.org/guides/getting-started
If you're doing
import { isEqual } from 'lodash';
it's importing the whole library.
Webpack 4 supports tree-shaking so you could do
import { isEqual } from 'lodash-es';
instead.
Who gives a shit?
Also, tree shaking is not a silver bullet. It only makes a difference if the library supports it by packaging the functions into separate files or separate, side-effects free exports in the same file that you can and do import separately, not with import *
. See here
Webpack is more project agnostic, and works really well with NPM for example. It's also supported by a lot of companies (you're shooting yourself in the foot if you're not using it) and therefore considered a modern web standard. As far as I can tell, CodeKit does kinda the same but as a paid alternative which contains less features overall. Honestly, Webpack is awesome and supported by the mass online, it doesn't hurt to learn how to use it! Especially if you are going to do some more specific tasks, such as integrating TypeScript (https://webpack.js.org/guides/typescript/) or wanting to share Sass resources across your whole project (https://itnext.io/sharing-sass-resources-with-sass-resources-loader-and-webpack-ca470cd11746).
Some of the problems I spot on your config file: - i believe you can't have 2 different output config - webpack entry point can't be anything other than js - i believe webpack can't spit out output into different folders
I believe what you want is to export multiple webpack ~~export~~ config. So instead of exporting a config with multiple entry points, you should export an array with 2 config, one for your app, one for your admin.
See docs here: https://webpack.js.org/configuration/configuration-types/#exporting-multiple-configurations
Since the config is just an object, you can create a base config object with scss loader and plugins, then extend them (with different entry/output) then export both in an array.
Hope that helps!!
edit: if your dashboard folder is inside your app folder, you'll have to exclude that folder in your app config's module
Well, bundling the dependencies is a thing, wether you like it or not I'm not here to convince you otherwise. However if bundling, versioning ensures that if your app is updated the user will use the new version (which is identified by the persistent hash) instead of whatever is in their cache and splitting cuts the download in half, assuming you update your code often but dependencies - not so much.
This suggestion is almost certainly overkill for what you're looking to do, but I'll include it for discussion:
I've used Webpack's DLL plugin to swap in different modules at runtime that needed to change more often than builds did. These modules were more complex than a simple JSON so that's why I chose to use DLLs.
I would suggest using http://browserify.org/ or https://webpack.js.org/. These will have good documentation and examples.
I personally use rollup but its not simple to configure it to do what you want.
The way I do this, is I set up a normal Node project and then keep all of my React code within a directory, I usually call it client
, in the root of my project. Make an index.js
file in the client
directory and use this as the entry point to the React app. You will need to use webpack with babel to bundle your code and turn your ES6 and JSX into older ES5 code that is compatible with older browsers. Here are the websites for webpack and babel. Configure webpack to output the files to another directory that is in the root of your project, public
. In your HTML page, put script tags with src
s to the files in the public
directory. Once this is done, you will be serving HTML files from your Node server and the HTML files include script tags that include your custom transpiled React code.
With regards to routing, you can use either. I would recommend making all requests to your Node server serve the same HTML file. This file could link to React code, where you can use react-router
to control routing.
If you want to create APIs on your Node server, for example /api/users
, you could implement that route within your Node server. Then in the React code, use a HTTP client package such as Axios
to make HTTP requests to the API routes on your server. This will return the data that was sent by the Node server and you can use it in your React code.
I hope I've explained that well, but if you have any questions, just ask :)
Your build tool would have a "production" config which would invoke things like concatenation, minification, optimization, etc. Here's a pointer from the Webpack docs: https://webpack.js.org/guides/production/#minification. The TL;DR is one or two configs that are very similar with slight configuration changes for local vs prod builds.
I see. Yeah, using an NPM package in the browser isn't really inutitive. The "industrial" solution is by writting code to import it:
import { Waypoint } from 'waypoints'
const waypoint = new Waypoint({ element: document.getElementById('thing'), handler: function(direction) { alert('You have scrolled to a thing') } })
The import
keyword is part of "es modules" -- it's an official part of JavaScript but not implement by most browsers yet.
A module bundler like Webpack goes through all the imported files and combines them into a single file that will run in a web browser.
Alternativly, Waypoint's getting started guide suggests downloading a pre-built file and including that in your webpage with a script element. A modification to this is pointing the script element at the pre-build file in your "node_modules" folder, since techincally you have downloaded the pre-built files from NPM -- the repo includes them in the "/lib" folder (This requires the "node_modules" folder to be served by your web server).
A third option is a service like https://unpkg.com which allows you to include any NPM package in your webpage using a script element.
If I am understanding your question, I generally like to approach this with environment variables. For example, if you are using the Create React App project, they have .env support already baked in. The idea is that upon compile, the build step uses Node's and Webpack's ability to fetch the current ENV values and set them as value within the code.
So, locally you can set the ENV values to point to localhost, on your testing platform you can use test server URLs and on production you use the prod URLs. If you are not using CRA, you can do configure Webpack's Environment Variables. Most build tools support some kind of ENV system out of box.
The challenge with ENV values in React apps is these values are extracted at build time. In most cases, with CI/CD this is a simple process. Each CI/CD build step has it's own unique ENVs. But, if you are building locally and then pushing the built assets manually you will need to keep this in mind and be sure to set the correct values during each build step.
This process should also work seamlessly with Server-side rendering because your server apps should have access to it's own ENVs.
So I've done a lot of this, if you're already using webpack then you should probably stick with that and not introduce another build tool.
Under the rules section of the config you can include tests to for scss files, as well as running all your js files through babel. (The ExtractTextPlugin is for straight css files.)
You'll want to change your output
to be something like,
output: {
filename: './static/[name]'
}
This will place both your compiled css and js into the same directory, so you'll want to modify the path in your templates (or the output, the point is to make it dynamic).
Webpack will do lazy module loading when you put a require() or import() inside your code as opposed to on the top of the module file. When you have lazy module loading it will create a separate chunk that will dynamically be loaded at runtime when you hit that line of code. https://webpack.js.org/guides/lazy-loading/
I was exactly the same a year ago. Although typescript looked good compared to classic javascript, the build process and integration into the page felt wrong. Using webpack now it still feels wrong somehow (especially when i look into the webpack config file) but it actually works pretty well.
So on your question of D3, if you're concerned about bundle size, you can import the individual D3 libraries to reduce unnecessary excess modules. This is similar to what people do with lodash and the general direction SPA frameworks are going.
A potential little trick of you're worried about size or network calls, you can use D3 as an external dependency in Webpack, so the resource is loaded via their CDN instead of your host. This might not seem like it would gain much performance, but for common libraries there's a fair chance your user will already have the library in cache, saving a network call. See more
Node is not a server. It is an independent platform. You can use it on your server, but also on the frontend as a foundation for your build tools.
Webpack is not hard to use, follow a couple of examples on their page and you'll be up and running fast: https://webpack.js.org/
Most frameworks also give you tools to make it easier. Since you mentioned JSX you probably use React, in that case you can use create-react-app. But all frameworks have them. Internally these cli's rely on node and webpack again.
Yes, unless you specify otherwise, React will be bundled alongside your code. You can use externals in webpack to avoid that.
I'd suggest looking on GitHub at the sources of other React component libraries for reference to see exactly what they're doing.
At first I thought that this was caused by bug 1405469, but then I found out that the webpack header image is also broken in release 56.0, also the spinning cube is rendered using HTML and CSS, not SVG.
I agree that there is nuance. My recommendations were based on the OP saying that he or she feels kind of lost and is trying to set up a new project. To that end, I think a tutorial that quickly gets to something being rendered on the screen would be a better starting point. But I can understand the mentality of building knowledge from the ground up.
You are certainly right that webpack also requires loaders and plugins, and I was unfair in not mentioning that. However, I maintain that the learning curve is steeper for Gulp. Just compare its documentation with webpack's documentation. The fact that webpack is only a module builder is probably a good thing, considering OP's situation. Things like minification, source maps, and incremental rebuilds on file changes are just flags. You don't have to choose and install other modules for them.
I know they are not 1:1 tools. My claim is that for a typical website, webpack does enough of the work that what's left over might as well be handled with plain scripts, directly using the tools involved, rather than going through Gulp. That's why I linked to that blog post in my third point. Even on small projects, I like to use webpack + plain scripts, but I'd be happy to hear about situations where Gulp is superior to what I'm doing. Maybe I'm missing something.
I hesitated to make my original comment since the OP specifically said he or she wants to learn Gulp, and I know "why wouldn't you use x instead?" posts can be annoying. I posted only because of the OP's comment about feeling lost. I suggested an alternate route in the hope that it will save the OP some pain/frustration. To answer the original question, here's a tutorial that might be helpful: https://www.sitepoint.com/introduction-gulp-js/
There are several ways:
Your app as a CLI tool using Node, which has system access. Node also has several ready-made excel packages.
Or wrapped into a native-like desktop shell through Electron which combines a portable Chromium with Node.
If the amount of files is fixed, a bundler like Webpack will pull them all in, you can require
them in your code, no server needed.
You could run a small node-based server locally.
As a last resort browsers can be run with command flags to allow local fetch requests.
You should definitely look into entry points of your webpack configuration. You can define multiple entry points and with that you end up in multiple bundle files. These bundle files need to be injected into HTML files then. This can be done with the HtmlWebpackPlugin then. Probably you need to inject or use some template to get the webpack bundle into html then.
Also for each entrypoint you need one HtmlWebpackPlugin, there you need to include the chunks you want to get into this HTML as parameter chunks: ['testSystem']
which is an array. Chunks are actually the keys of the entries:
entry: { testSystem: path.resolve(dirname, './testSystem.js'), fooSystem: path.resolve(dirname, './fooSystem.js') }
So you could also include two chunks inside the HtmlWebpackPlugin and get two chunks available via Templating engine of HtmlWebpackPlugin. The template should include something like this then:
<% for (var chunk in htmlWebpackPlugin.files.chunks) {%> <script src=<%= chunk %>.<%= htmlWebpackPlugin.files.chunks[chunk].hash %>.bundle.js></script> <% } %>
Probably you need to adjust paths depending on your configuration and also look into the variable htmlWebpackPlugin (you can json stringify it and show it in the HTML template you are generating then).
I just use dynamic imports in webpack 2 with modules: false in my babel-loader, and it works fine on both the server and client: https://webpack.js.org/guides/code-splitting-async/
My server environment isn't even node, it's Nashorn...
Am I missing something here?
Move your index.html
into your src
directory. It's part of your application and gets equally transformed by Webpack - it's not a public
asset that gets served unchanged.
You're using copy-webpack-plugin
but your index.html
is being transformed by html-webpack-plugin
. You do not need copy-webpack-plugin
.
You're using Webpack 2 but the Webpack 1 syntax. Instead of module -> loaders
it is now module -> rules
, with slight changes to some loader properties. While this has been made to be backwards compatible for now, if you're starting a new project, you should use the new syntax.
You've got a lot shared between your Webpack production
and development
configurations. Consider moving these out into a common
base configuration - and conditionally adding plugins based on process.env
or by using a tool such as <code>webpack-merge</code>.
Your current babel configuration will not take advantage of Webpack 2's tree-shaking. Consider adding modules: false
to the configuration of the es2015
preset.
Don't use cd
and python
in your package.json
scripts. These are OS specific and the latter relies on python
being installed. Using a package such as <code>http-server</code> will allow you to serve your build with only JavaScript.
Note that process.env.NODE_ENV
is not entirely what you want, because that part of the code will only run when bundling. You need to use a combination of process.env.NODE_ENV
and https://webpack.js.org/plugins/define-plugin/ to do that.
Basically, DefinePlugin defines variables and values that the variables will be replaced with when bundling, so the example from docs:
new webpack.DefinePlugin({ PRODUCTION: JSON.stringify(true), })
Will replace your code:
if (!PRODUCTION) { console.log('Debug info') }
with
if (!true) { console.log('Debug info') }
So what you want is:
new webpack.DefinePlugin({ 'NODE_ENV': JSON.stringify(process.env.NODE_ENV), })
and then in your code:
if(NODE_ENV == 'production') { // this code will run in production only }
Everyone is saying the docs are excellent, but they're assuming some things where I've had to use YouTube videos to create my first bundle. Right from the start, after saving webpack as a dev dependency: https://webpack.js.org/guides/installation/
>To run the local installation of webpack you can access its bin version as node_modules/.bin/webpack
I can't do this on a Windows machine, and have seen a number of versions of this giving a path followed by an input and output file to run webpack before you have a script setup.
with powershell (or commander): 'node_modules' is not recognized as an internal or external command, operable program or batch file.
webpack ./index.js bundle.js works -> but I understand this is using the global install of webpack.
Am I overlooking something they don't mention in their step-by-step like I need a config file first?