I am a dev on a web application that consists of Java Server Pages which act as the HTML, a Java backend, and Javascript front-end files. I have been tasked with looking into adding Webpack to the project, with the goal of only using it to minify Javascript files at first (eventually we will use more of Webpack's features of course). I have tried doing research via Google into Webpack minification, but I am having trouble finding anything detailing how to use it for just minification, instead of bundling the project files.
Does anyone know how to use Webpack for strictly Javscript minification?
Webpack out of the box is anticipating on processing JS and will run minification on production builds by default.
https://webpack.js.org/configuration/mode/ (different build modes)
Assuming you are already past configuring a JS entry file to consume all your JS files:
https://webpack.js.org/configuration/entry-context/#entry
AND configured a loader on how to handle each JS file imported in your entry file appropriately.
(Feels like you want asset/resource. Pay close attention to asset modules type and generator options)
https://webpack.js.org/guides/asset-modules/
The settings for minification on a production build are what is known as the optimization.minimize configuration of your webpack.
https://webpack.js.org/configuration/optimization/#optimizationminimize
With Webpack5, further options around the minification engine has been exposed and is known as optimization.minimizer configuration options:
https://webpack.js.org/configuration/optimization/#optimizationminimizer
Related
I am trying to deepen my understanding of modules in JavaScript beyond just using CommonJS, AMD and ES Modules.
This has lead to me look more into webpack to understand how it actually makes modules work in the browser without relying on the still relatively new ES Modules. From what I understand, Webpack bundles the JS, converting import and require statements to its own statements and ships it with a runtime and manifest which allows it to execute them. So Webpack has gotten past the lack of module support by basically implementing its own?
I have tried to compare this to a different bundler — Parcel, but I can’t seem to find any information about how it handles modules.
Does anyone know if my understanding of Webpack is correct, and how that compares to how Parcel does it?
Appreciate any help in advance.
Thanks
The implementation of the ES6 import/export syntax has rendered many traditional module loaders such as RequireJS / AMD and rollup somewhat obsolete. However, asset bundlers like Webpack and Parcel still find their place in modern web development.
An assets bundler packs multiple files into a smaller set of files (including JS, images, fonts, LESS, SCSS etc.), thereby reducing the number of requests to the server and communication overhead. The bundling process typically involves script minification, dead code removal and dependencies management. This also allows more modular front-end web development.
In some ways, Parcel, being newer, is more advanced than Webpack. Parcel supports many different languages and file types out of the box, from web technologies like HTML, CSS, and JavaScript, to lower level languages like Rust, and anything that compiles to WebAssembly (WASM), to assets like images, fonts, videos, and more. You can build multiple targets at once and live-update them as you make changes. Parcel compiles all of your files in isolation in parallel inside workers, caching all of them as it goes along. No explicit configuration is needed for code splitting using dynamic import() statements.
Both Webpack and Parcel provide you a development server to test your project on a browser. Unlike Webpack, the entry point of Parcel is an HTML file instead of a JS file. You should not declare type=”module” within the < script> tags.
Another asset bundler is Browserify. It is a simpler tool which merely bundles your files. It is not as rich in features as Webpack and Parcel.
I watch a lot of tutorials of angular 2, and I couldn't some questions:
1- Should I use webpack for minification and bundleling?
2- Should I minify and bundle the js of the components itselfs.
3- Should I minify and bundle the js services that the components expose e.g.
personService.js is used in person.ts?
4- What happens with the path
of the service I provide inside the component, now it will be in one
file located in another place? Should I change the path of the
service called in the component depending on if I'm in development o
production?
How are you currently handling module loading for your applications? I'm not as familiar with webpack, but SystemJS offers a builder/bundler that will do all of this for you then all you need to include in your html is the script for your bundled/built file.
I haven't used Webpack but SystemJS worked well for me. Gulp can be used to build, minify, and bundle all your code using a system.config.js to worry about the file locations of your source and dependencies.
Here is an example of Tour of Heroes where all the Typescript source is bundled into one JS file.
Angular CLI now makes all of this really easy, supporting bundling and minification (using WebPack underneath, but without any need to set it up), and Ahead-of-Time template compilation, which massively reduced the bundle size.
See: Angular 2: Reduce app size (in addition to bundling/minification)
It also sets up development and production environments, which you can import into components if you have different settings in dev vs. prod, and you can make your own custom environments and use those too.
I am using Webstorm a start a angularjs project. I've created a lot of *.js files. I have the include them using the tag one by one in the html files. whenever I created a new js file, I have to create the script tag.
The things I needed is just like gulp-concat, but without minifying. minified code are hard to debug.
Can anyone help on this? Thanks!
WebStorm doesn't have any built-in functions for combining files... But there are plenty of different tools on the web - plus you can create your own batch files for this.
I can suggest using Grunt grunt-contrib-concat task (https://github.com/gruntjs/grunt-contrib-concat). It supports merging files. You can run the task using Node.js run configuration, or configure it as a file watcher, or use Grunt console.
Browserify (http://browserify.org/) is one more way to go - it allows using commonjs-style syntax when developing front-end applications, combining the files into a single file for production
Or, try Webpack (https://webpack.github.io/) - it's a modern powerful module bundler
We want to use Google Closure in our build process as follows:
when in development mode, include base.js and dynamically add script tags
when in production, use minification and all the other cools stuff
This is a Java project running on Tomcat and we are transitioning from Maven to Gradle, and have continuous integration set up using Jenkins. We use Apache Tiles as a frontend technology.
I came up with a possible solution, but I feel it painful and ugly, and would like to know if there are better (cleaner, simpler, etc...) solutions.
My stinky solution:
Use a Tomcat context parameter to identify production mode. In the JSP files, check for this variable and include Closure's base.js or the minified js file accordingly.
So... any other suggestions? Possibly with pros/cons?
I use Grunt for this. Grunt is a tool to automate frontend minification, compilation, unit testing, etc.
URL: http://gruntjs.com/getting-started
In Grunt, you create a Gruntfile and register a task that consists of one or more reusable configs. A config does something like: "minify all files in this directory and output to that file". So what you would do is register two tasks: one for dev and one for production, with some configs in common, and some configs specifically for that environment.
You can pass your Tomcat context parameter to Grunt as a parameter (cleanest), or alternatively read it as an environment variable inside the Gruntfile and create an if branch in the configuration.
Grunt has a lot of plugins: The plugins you need are already available:
Conditional including/excluding of files: native support
Generate script tags: https://github.com/Zolmeister/grunt-sails-linker
Google Closure Compiler: https://github.com/gmarty/grunt-closure-compiler or https://github.com/blaise-io/grunt-gcc-rest
I'm investigating the complexity involved in maintaining a cross-platform (web, ios, android) phonegap codebase that allows for platform specific code (and assets/tests) as simply as possible.
The current best approach I'm taking is to use grunt to build the code of a typical web app, and then use the grunt-phonegap module to generate the respective phonegap projects.
I'm confident this will work, however for my phonegap projects, I know I'm going to need to make use of some specially written plugins to make use of some device capabilities (these aren't typical cordova plugins)
I'm wondering if anyone has figured out an approach for maintaining a codebase that can adapt to different platforms and requirements. Javascript has no #IF_DEF functionality, but would it be possible to implement something like that using grunt?
I recently had the same question myself. I couldn't really find much online regarding this so I decided to deep dive into Grunt, Node, and Git.
Grunt and Node
In the root folder of my Cordova projects (alongside the www, platforms, merges, and plugins folders) I have a grunt project. I store modular JavaScript files and CSS files that may or may not be platform dependent inside a src folder inside the root of the Cordova project. This grunt project builds the JavaScript and CSS stored in the src folder and places the resulting files into the www or merges folder as appropriate.
I even wrote a grunt task that will make a production build of the app by optimizing and minifying css, javascript, and html templates, then rebuilds the Cordova platform projects to include these production files.
Because there is no #IF_DEF in JavaScript, I have to use Grunt (mentioned above) to build out the JavaScript for each platform. I modularize almost all of the JavaScript functions by platform. If there are no platform differences for that function (no native hooks), I only need one file. If there are differences, I need to create a separate file for each platform for that function. For example, my Cordova onDeviceReady and onResume function usually differ from platform to platform. I create files called
CordovaEvents-ios.js and CordovaEvents-android.js
Inside the package.json file, I describe the "features" I want in my app. CordovaEvents is an example of a feature.
I also support "arguments". I use the same approach above in the file names of the modular files. An argument could look like this
CordovaEvents-ios--production.js and CordovaEvents-android--production.js
In this case the code needed in a production app will differ from non production code. I can simply pass this argument (or list of arguments) during the build process, and the correct files will be picked up and built. I think this most closely addresses your question if there is an approach to maintaining a codebase that can adapt to different platforms and requirements. The requirements are the feature names and arguments. The argument can be anything you want, maybe using one plugin or another plugin.
I also describe the platforms I want to support ("iOS", "Android", and "Desktop"). Grunt processes each platform in a MultiTask, and then looks at the features I want to support. It will try to find a file called feature-platform.js. If it cannot find this file, it will just try to look for feature.js. After I concatenate all the functions together needed for the platform, it will copy the file over to the merges folder for iOS or Android. Typically all the files kept in the WWW folder in the root project will work on a desktop because there are no native Cordova hooks... this allows me to debug in Chrome. All the files that contain native hooks are stored in the merges folder. Once the Cordova project is built for the respective platform, the code can be tested in a device simulator.
If you are new to Grunt I would strongly suggest taking a look a their getting started guide.
http://gruntjs.com/getting-started
Git
I also employed Git to version my code. I used SourceTree to create the Git repository in the root folder of my Cordova project, and have a remote repository on my Mac Mini server that I can push my commits too. This allows us to have a backup copy of the code, and makes it so my team can also work on the code out-of-band.
I Git ignore the following folders:
node_modules
plugins
platforms
plugins
All the other files and folders contained in the root directory of my Cordova project are versioned. I used the following link as a reference to help define my Git strategy for Cordova:
https://leanpub.com/developingwithcordovacli/read#version-control
It didn't take me overnight to figure all this stuff out, in fact it took a little bit more than two months. I hope my answer can server as a guide to you and others to address your concerns you mentioned in your opening post.
I am using gruntjs, javascript, jade, bower, and phonegap to build hybrid web applications and phonegap mobile applications. After some investigation, I settled on to use jade template language for creating my html and javascript files. This is my setup.
//begin grunt module
module.exports = function(grunt) {
var $jadeConfigObject = {
compileDevelopment: {
options: {
pretty: true,
data: {
debug: true,
**phonegap : '<%= isPhonegapBuild %>'**
}
},
files: [{
expand: true,
cwd : "src",
src: "**/*.jade",
ext: ".html",
dest:"dist/development/www/"
}]
}
};
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
clean: [$dist_folder,"www"],
jade: $jadeConfigObject
// other gruntjs tasks
})
grunt.registerTask('setPhonegap', 'Set Phonegap related values.', function(n) {
**grunt.config.set('isPhonegapBuild', true);**
});
grunt.registerTask('buildPhonegap', ['setPhonegap','buildDevelopment'
,'copy:phonegap_www']);
}
Now explanation
Use gruntjs setPhonegap task to distinguish between phonegap build and normal web application build.
Task setPhonegap set isPhonegapBuild config property, this property, in turn, is used by jade config object. Then I can use "if phonegap" statements in jade files.
I have following line in my jade layout file
include ../includes/mainJavascript.jade
mainJavascript.jade
if phonegap
script(type='text/javascript',src='#{mainFolder}/cordova.js')
script(type='text/javascript',src='#{mainFolder}/cordova_plugins.js')
script(type='text/javascript',src='#{mainFolder}/plugins/org.apache.cordova.device/www/device.js')
script(type='text/javascript',src='#{javascriptServicesFolder}/pushTokenService.js')
script(type='text/javascript',src='#{javascriptFolder}/plugins/com.phonegap.plugins.PushPlugin/www/PushNotification.js')
script(type='text/javascript',src='#{javascriptFolder}/phonegap/pushNotificationHelper.js')
This way I have following features
My web application does not contain any phonegap related scripts or html
I can use jade layouts (Master Page) to simplify my files very easily.
Adding new javascript to every page or changing every html for every page in application very easy.
Note that phonegap wants www folder for its build scripts, therefore I create following directory structure.
src -- every code file here, jade, javascript
www -- only created for phonegap build
dist/development/www -- normal development www build
dist/production/www -- production www build
I ignore www/* and dist/* in my source control. I only work with src jade and javascript files. Add this setup to bower, I believe it is a good option.