Webpack 4 referencing npm vendor scripts - npm

I'm trying to get my head around Webpack 4 for a medium-to-large scale (MVC) website.
For the solution, I want to use the following, base vendor scripts/styles:
jQuery vLatest minified version
Bootstrap, but only the grid, no javascript or anything else
The site consists on several templates different from each other. Some might have an image gallery where I want to use Owl Carousel vLatest and so on, so forth.
As I've understood, the vendor bundle should only contain the scripts/styles that is used across the entire site, so i.e., the Owl Carousel script/styles should not be a part of the vendor scripts since it's only used for one, maybe two specific templates.
I've installed jQuery and Bootstrap via npm so they're in the node_modules folder. Question is: how do I tell Webpack to use the minified version of jQuery in the vendor bundle? And how do I tell it to use only the grid component from Bootstrap? And what about the other third party scripts/styles, should they be included as their own entry?
My webpack.config.js entry file looks like this:
entry: {
'mysite.bundle.css': './scripts/webpack-entries/mysite.styles.js',
'mysite.bundle.js': glob.sync('./scripts/mysite/*.js'),
'vendor.bundle.js': [
'./node_modules/jquery/dist/jquery.min.js'
],
'vendor.bundle.css': [
'./node_modules/bootstrap/scss/bootstrap-grid.scss'
],
}
What feels weird about this is, that I could just aswell reference the jquery.min.js directly on my view and import bootstrap-grid.scss directly in my .scss files. Same could be said with the Owl carousel (and other vendor scripts)
Also, if I just do this: 'vendor.bundle.js': ['jquery'] the entire non-minified jQuery library is loaded rather than the minified version.
How exactly do you work with Webpack and NPM this way? :-)
Thanks in advance.

You can use { resolve } to configure aliases:
{
resolve: {
alias: {
'jquery': require.resolve('jquery/jquery.min.js')
}
}
}
However, I would caution first to focus on getting a viable build that's suitable for development and then enhance the configuration as needed to optimize for production. For example, during development you want to include all the sources with their entirety with good source maps. When you get to the point of publishing, use something like Environment Variables to introduce a flag that will enforce the necessary configuration.
No, it's not necessary to create entry points for particular vendor sources. This is reminiscent of the past practices. You should create individual entry points to logically split your large codebase into distinct bundles, like: the public web, the administrative application, the customer application, should you have the need to do so.
Also, don't spend too much time creating entrypoints to group vendor sources and such. Write your modules as you would, from the perspective of a developer, require from them what they depend on and then use webpack { optimize.minimizer }, other minification plugins and it's dependency graph heuristics to create necessary chunks using { optimize.splitChunks }.
Short answer is, and this has been true for webpack for a long time: do not change the way you write and organize sources to satisfy webpack. It's polished and sophisticated enough that it will accommodate to your style of authoring.

Related

loading different scss file based on current language - nuxt

i'm trying to implement rtl/ltr in my nuxt application.
this is my project structure
|--assets
|--scss
|--**/*.scss
|--bundle.scss
|--bundle-rtl.scss
so styles are compiled into the bundle and bundle-rtl normally.
the problem is this .. how can i switch between theses two scss files without changing them manually within my nuxt.config (automatically change the scss file when the language is changed).
among these files is a mixin file with many mixins related to rtl and ltr switching so i need to use them in each vue file that i have. which is why i can't just compile them to css (with gulp or webpack for example) and include them in head.
aside from all of this, is this the best way to implement ltr/rtl in nuxt or is there a better way?
In my opinion, you should write modern CSS that takes this into account rather than having a duplicate. This will have the benefit to also be usable by other languages.
Check this awesome article: https://css-tricks.com/building-multi-directional-layouts/

rollupjs avoid duplicated functions with multi files

I'm trying to pack all the common libraries to be used with multiple projects without an actual entry files. Thus I need all the functions to be included in the bundle
Thus I'm trying to achieve that using #rollup/plugin-multi-entry pointing to all the files inside the directory
The problem I'm facing currently is that, some of the files extends each other, when packed, the extended function is duplicated multiple times with the name $n and so on, is it possible to make rollup not duplicate those extended functions?
Thanks
Bundling libraries inside a vendor file is now considered an anti-pattern since you will neglect the benefits of three-shaking. It will also come with worse caching since every time some lib changes the cache of the whole vendor will be invalidated and, finally, you won't benefit from http2 multiplexing that much.
If you still want to do it, in order to give them reliable names (and avoid naming conflicts) it is much easier to do it manually:
// vendor.js
import * as lib1 from 'lib1';
import * as lib2 from 'lib2';
export {lib1, lib2}
The previous module, when used as entry point, will result in exporting all exports from both libraries under its respective namespaces, and rollup will internally handle dependencies between libs correctly.
Edit: if you can bundle the libraries along with the project and not in a different process you can do it like so:
// rollup.config.js
const libs = ['lib1', 'lib2'];
{
input: 'index.js',
manualChunks: {
vendor: libs.map((lib) => require.resolve(lib))
},
// ...
}

Am I handling correctly multiple projects with a common code base?

I am creating several mobile applications in react-native that share common components. I have difficulties handling the dependencies. Here is what I do, which is tedious, is there a better way?
A repository "common-modules" has shared components
Several repositories include the common one as a dependency like this:
Package.json
"dependencies": {
"common-components": "file:../common-components"
},
I use it like that in the different apps:
import XXX from 'common-components/src/...'
Now this is great because all other dependencies are in "common-components", but as soon as one of them has native code, I am forced to link the library again in each app.
For instance, if I use "react-native-image-picker", I have to install it again in each application and link it in XCode, edit build.gradle etc. etc.
It takes forever
Are my linked dependencies bundled twice?
I fear the day when I must change/upgrade one of them...
Is there a better way?
I've heard of projects that share code being managed in a monorepo. That may help managing shared code but won't solve the problem of linking native modules N times for N apps.
However, there is react-native link that should automate the process, and ease linking the native modules a lot. Note there is no need to re-link if you just upgrade a native dependency.
Alternatively, I think it should be possible to wrap multiple native modules into one. If you take a look at MainReactPackage.java in RN repo, it wraps several native modules. I imagine similar mechanism can be employed on iOS, with static libraries. Obviously, this means that it won't be easy to selectively include some modules and others not.
Like you said yourself it is easier to work with a duplicated codebase. To deal with that you can create your own package manager for your shared components. Make a script for each component which will add it's dependencies to package.json and configure gradle and XCode. Add a simple GUI to include your components with a single click.
This may seem like a lot of work upfront, but:
- you will keep full control
- once you have a script to install a component you will save time each time you use it on a new app
- in the case of updates you can create a script to handle that as well

Dojo custom build: which files to deploy

First, we're new to Dojo and are free do things the "new" way, so I'm mostly ignoring the pre-1.7 sections of the documentation. Still, I'm coming up confused when comparing various articles, documents, and sample scripts.
The bottom line is that I can't find a straightforward write-up on how to create and deploy a custom build for Dojo. Most specifically, which .js and .css files we need to deploy. There's a lot of documentation on creating a build, but none I've found on deploying.
I eventually gathered that building everything into a single dojo.js is a reasonable practice for mobile, and that I simply have to extract that one file out of the build directories and deploy it to my server, but then I get missing CSS references, and it doesn't seem like trial-and-error is the correct way to resolve those.
Here's our specific, current case:
<script type="text/javascript">
require(
// deviceTheme to auto-detect device styles
[
"dojox/mobile",
"dojox/mobile/parser",
"dojox/mobile/deviceTheme"
]);
</script>
Here's the build profile:
dependencies = {
stripConsole: "normal",
layers: [
{
name: "dojo.js",
customBase: true, // prevent automatic inclusion of dojo/main
dependencies: [
"dojox.mobile.parser",
"dojox.mobile",
"dojox.mobile.deviceTheme"
]
}
],
prefixes: [
[ "dijit", "../dijit" ], // example included; not clear why
[ "dojox", "../dojox" ]
]
}
(Executed by the dojo-release-1.7.2-src\dojox\mobile\build\build.bat script.)
So I guess the specific questions are:
Which CSS files do I deploy for this case?
How do I know in general which files, including CSS files, to deploy?
Is there a good, current tutorial that I'm missing?
Are the existing scripts up-to-date? For example, why does mobile-all.profile.js use dependencies= instead of the profile= that the 1.7 build tutorial describes?
Which CSS files do I deploy for this case?
This is conditional, if a page uses a specific module and it has its own css-rules, include them.
This is not the way, but starting out with dojo.css (base, reset), dijit.css (base, layouts and more), nihilo.css (example theme) and android.css (example theme) would make a good foundation
If you want to use a theme, include the 'basename', e.g. dojox/mobile/themes/iphone/iphone.css
If for instance iphone.css does not '#import' some exotic widget you use, include the css which is delivered by the widget itself (as example, dojox/widget/ColorPicker/ColorPicker.css). Docs for each widget _should make not of this.
How do I know in general which files, including CSS files, to deploy?
There is no harm in uploading all files, the loader will decide which to get from cached-build, which to leave alone and what to download during runtime.
deploy everything.. when you build a 'action=release' all files are minified within the prefixes defined dojo (defaults, allways), dijit, dojox and any packages you add.
the build results in optimized toolkit-tree, deploy all or you might face a situation where a conditional include (Toggler.js for instance, or acme.js selector incl etc) is missing.
Is there a good, current tutorial that I'm missing?
By 'thumbrule', any 1.6+ docs are stable, but they mostly say the same. As you start a profile, it may get a bit trial and error (the sequence of inline-html inclusion of script files is of outmost importance). What you posted looks good, though think about if customBase:true is nescessary.
Make sure you have seen this for versions 1.6-1.7 and version 1.8
Are the existing scripts up-to-date? For example, why does mobile-all.profile.js use dependencies= instead of the profile= that the 1.7 build tutorial describes?
You can use the existing ones, out the box. The builder however is changing, moving up against the much debated 2.0 release. For now, the new schemes are allowed as well as the regular ones. But in fact the variable name can be foo or bar, only the variable's value is put to use. The file must 'return' a single object.
As i understood, the reason is that CommonJS Packages/1.0 is the new bible for AMD and builder 1.7+. It has allways been the 'thumb' scheme the package hierachy has followed however - but the syntax will most likely get more and more strict the closer we move to 2.0. (see if you can hook up with snover on #dojo # irc.freenode.org)

DOJO build that does not include DOJO base

Is this possible using v1.6.1? Due to the Xdomain configuration of my client's dojo deployment, it is necessary to execute a new build each time dev code changes. As you can imagine, this is a huge time waster.
From everything I can see there is no way to exempt the core from the build playing by DOJOs rules. So I am wondering if there is a way to break the rules (modifying the Rhino calls?) to get to where I need to be.
A couple thoughts.
You can avoid building most of dojo (dijit, dojox) but I imagine you already know that
This restriction you are facing seems odd. Isn't there some way you can just upload the specific JS files you are editing during development?
Maybe if you give more details on the client setup, I can help you brainstorm a way around this problem.
Update
Here's what I think you need: Customize Dojo Base in Build. This allows you to specify particular bits of the dojo base to include.
This works in pre-1.7, so you should be good.
Appears to be exactly what you want:
layers: [
{
name: "dojo.js",
customBase: true,
dependencies: [
]
},
// ... remainder of profile
]
This will give you the absolute bare minimum of dojo (which you still don't need for your dev scenario, but which will drastically reduce the amount of files processed).
For other use cases, you can use the dependencies attribute to add in other stuff from dojo core.
Update 2:
Here's a couple build-time optimization suggestions:
1) Don't intern strings, and don't compress, when in dev.
There are arg values you can pass to avoid these time-consuming steps (example is for ant build):
<arg value="internStrings=false"/>
<arg value="layerOptimize=false"/>
2) Build to a ram disk to speed copying of files
Dojo supports mix-and-match - so you can use xdomain and/or custom build for the stuff that does not change - and use regular dojo.require for the JS/widget that is changing often - and then just push that JS to see the change without a new xdomain/custom build/deployment
You can explore using local modules with xdomain build. Also, Dojo allows using multiple custom builds - so you can do a stable custom build for the widgets that don't change so much and another smaller build for code that is changing frequently.
Why not use dojo 1.7, load asynchronously, and rely on it's legacy support? http://livedocs.dojotoolkit.org/loader/amd