Generate sourcemaps with requirejs without including sources? - javascript

I'm using grunt and requirejs to build and compress our app for deployment. We want to create source maps that can be used for debugging client code remotely, without exposing our uncompressed dev code. In the requirejs options, I'm specifying for optimization:
options: {
// ...,
optimize: 'uglify2',
// ...,
uglify2: {
mangle: {
except: ['jQuery']
},
compress: {
sequences: true,
booleans: true,
evaluate: true,
conditionals: true,
comparisons: true
}
},
generateSourceMaps: true,
preserveLicenseComments: false,
// ...
}
This generates sourcemaps as expected, but they include the source files inside the maps, which increases file size significantly and exposes our original dev code. UglifyJS2 docs says it supports a sourceMapIncludeSources option which I've tried passing in an options object in the uglifyjs2 config, but it does not appear to be respected here. Is there a way to get requirejs to generate source maps without including the sources, or to get it to respect the options passed to uglify?

Related

How to uglify production code in ReactJS?

Correction made to my previous Question (Instead ofObfuscate, I'm actually trying to find out Uglify)
I've recently began to work on ReactJS, while I try to bundle to code in production.. I realized all the codes are in readable format. I'm aware of the approach below:
Set false to generate sourcemap.
However, this way my code is still kind of readable in terms of my
API Endpoint
API keys
I'm trying to understand what is the proper way to fully uglify my code in production?
Here's how we can UGLIFY our code in ReactJS.
Run npm run eject
Run npm install uglifyjs-webpack-plugin --save-dev
Go to webpack.config.js at your config folder (you should get this folder after eject)
Search for keyword minimize: isEnvProduction then append the following at bottom
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
warnings: false,
parse: {},
compress: {},
mangle: true, // Note `mangle.properties` is `false` by default.
output: null,
toplevel: false,
nameCache: null,
ie8: false,
keep_fnames: false,
},
}),
],
If you now build your app npm run build for production environment, and you shall not see your code via Inspect Element.

how can i optimize main.js size?

I have a Vue.JS application. I'm creating it using webpack. I'm getting large main.js size after application build. (9 Mb).
I have any packages. But I'm getting large main.js size after creating empty application, too. How can I solve the issue?
You can use uglifyjs-webpack-plugin, compression-webpack-plugin to optimize your bundle size.
Here is my full code
Example:
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: false,
extractComments: 'all',
uglifyOptions: {
compress: true,
output: null
}
}),
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
safe: true,
discardComments: {
removeAll: true,
},
},
})
]
},
plugins: [
new CompressionPlugin({
test: /\.(js|css)/
}),
new UglifyJsPlugin()
],
So UglifyJsPlugin help you to minify and uglify js code. CompressionPlugin help you compress your js file into gzip extension.
But I would recommend you use webpack-bundle-analyzer to check the bundle size affect final build
There are several ways of optimising your main file and application performance. All of them works, but some might be not suitable for your case.
Code splitting and lazy load components.
In my case I solved problem by using code splitting and lazy loading components.
It turned main.js into very small one and other files are loaded when becomes visible.
Check this article about code splitting and this one about lazy load in Vue.js. It is very common approach in libraries like React or Vue.js.
Optimising libraries. No much to add, check if is possible to pull function instead of whole library (like in lodash) or use native implementation instead of external one. Unused npms also does not makes your main file lighter. Even if now you don't have much packages optimising them in future will make a difference.
Minifying and uglyfing. Most common and most important practice not only because of performance reasons but also because of security. Those two webpack plugins are the most popular webpack plugins at all:
UglifyJS - for JS
MiniCSS - for CSS
Webpack optimisation. Webpack knows thousands of tricks how to make your bundle smaller, but from time to time it might be your false friend. Remember to define how to resolve some dependencies, for example by pointing to proper node_module or library. It can looks like, where alias for lodash saved me a lot of kBs.
resolve: {
modules: ['app', 'node_modules'],
extensions: [
'.js',
],
mainFields: [
'browser',
],
alias: {
'lodash-es': 'lodash'
}
}
Code responsibly.
The best way to understand your problem is to analyse main.js, you can achieve it by adding Bundle Analyzer Plugin to your webpack config into plugins. It should looks like:
new BundleAnalyzerPlugin({
reportFilename: 'report.html',
analyzerMode: 'static'
})
Look into docs if you want to adjust it somehow. Interactive report is awesome.

How do I "add a served file as a dependency" in my Karma configuration for an Angular 2 project?

I am trying to update an Angular 2 project by implementing the changes indicated in the official Angular 2 change log.
(If you care to know the details, I completely worked through a tutorial that was built with Angular 2 version 2.0.0-beta.13 and want to now convert it to the current latest Angular, i.e. version 2.0.0-rc.6. The tutorial itself can be found on Youtube and the final code can be found on GitHub.)
I'm stuck at the following step: The change log for Angular 2 version 2.0.0-beta.16 states the following:
You will also need to add the dependency 'node_modules/zone.js/dist/fake-async-test.js' as a served file in your Karma or other test configuration.
I'm not sure I completely understand what that means, and I don't see an obvious way to implement it. The karma.conf.js file for this project is the following:
// Karma configuration
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['browserify', 'source-map-support', 'jasmine'],
// list of files / patterns to load in the browser
files: [
'test/init.js',
'src/**/*.spec.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'test/init.js': ['browserify'],
'src/**/*.spec.js': ['browserify']
},
browserify: {
debug: true,
transform: ['babelify']
},
specReporter: {
maxLogLines: 5,
suppressErrorSummary: true,
suppressFailed: false,
suppressPassed: false,
suppressSkipped: true,
showSpecTiming: true
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['spec'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultanous
concurrency: Infinity
})
};
I suspect the solution will involve a change to the above karma.conf.js file, but also possibly installation of an npm package, either through a command line npm install ... or, more likely, through modifying the dependencies in package.json. I don't know if this is relevant, but the tutorial's original (i.e. Ang2-beta.13) package.json lists zone.js ^0.6.6 as a dependency while the change log for the most recent Angular2 (rc.6) lists zone.js ^0.6.17 in its peer dependency updates.
Where have I looked? Well, I don't see an obvious place in this pre-existing config file for this new dependency to go, so I suspect that it might involve a configuration property not previously needed for this project. The questions asked by karma init seem too basic to be relevant. I have looked over the complete list of karma configuration options and don't see an obvious place for this (and that page doesn't even contain the words "dependency" or "served"). I have also looked over the official Karma documentation for files and plugins and neither provide an obvious solution.
So, how do I do what the change log mandates, i.e. how do I "add the dependency 'node_modules/zone.js/dist/fake-async-test.js' as a served file in [my] Karma ... configuration"?
It turns out that the answer is probably embedded in the change log for version rc.6. There, they state the following under "Breaking Changes": "testing config: due to zone.js peer-dependency upgrade, the order in which various zone specs are loaded has changed. Please see this example Karma config." That example karma config shows the following:
config.set({
files: [
...,
// Reflect and Zone.js
'node_modules/reflect-metadata/Reflect.js',
'node_modules/zone.js/dist/zone.js',
'node_modules/zone.js/dist/long-stack-trace-zone.js',
'node_modules/zone.js/dist/proxy.js',
'node_modules/zone.js/dist/sync-test.js',
'node_modules/zone.js/dist/jasmine-patch.js',
'node_modules/zone.js/dist/async-test.js',
'node_modules/zone.js/dist/fake-async-test.js',
...
],
...
});
I don't yet know how much of that list of dependencies is relevant, but at least it shows the syntax for including fake-async-test.js.
That's probably the best answer to my specific question. However, more generally, the linked example karma config file from the change log for version rc.6 is probably going to go a long way to helping me do the overall project update.

How do I resolve dependencies when linting single javascript files with grunt?

I want to separate my application logic into multiple Javascript files for sanity and developer friendliness, stored in the /src folder. These files should be linted and concatenated into /dist/app.js during the build process. I am using grunt for my build process, as it already comes with handy lint and concat tasks.
+
|- grunt.js
|- readme
|-vendors
|-backbone.js
|- src
|- core.js
|- user.js
|- dist
|-app.js
I am running into an annoying problem. I use backbone.js for application structure, and most of my source files start by defining models by extending Backbone.Model. When linting these files, JSHint complains that Backbone is not defined, and rightly so - backbone resides outside in its own directory. Including all necessary scripts in the right order is something I assume is done in the html. Each individual source file should only know about itself.
I know that I can suppress these undefined warnings by setting lint's undef flag in grunt.js to false but I want to keep it set to true in order to be warned about other undefined variables in my application, as it is a common pointer to typos. Is there a clean way to tell grunt (or lint) what files to include prior to linting them? Am I doing something wrong with my build process, or with my application architecture? Or is this simply something I have to live with?
The jshint options allow you to specify a list of globals that come from other libraries you are using, in your grunt.js file:
jshint: {
options: {
curly: true,
eqeqeq: true,
immed: false,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
boss: true,
eqnull: true,
browser: true
},
globals: {
jQuery: true,
Backbone: true,
_: true
}
},
note the globals setting at the bottom. This allows JSHint to ignore these variables, but still run your undef: true setting (as shown above).
An alternative approach (that doesn't rely on grunt) is to add a jshint comment into your js files:
/* global Backbone, jQuery, _ */

require js on build file combine

I use require js in my single page app and I am wondering if it is possible to combine all modules, vendor libraries (jQuery, Underscore, Backbone) in one single file, since this would speed up my app.
app
css
html
homepage
main.html
login.html
signup.html
js
build.js
libs
jquery.js
backbone.js
underscore.js
require.js
modules
collections
models
views
main
main.js
app.js
router.js
app-build
My build configuration file currently is:
({
appDir: '../',
baseUrl: 'js/modules',
mainConfigFile: 'modules/main/main.js',
dir: '../../app-build',
optimize: 'uglify',
uglify: {
toplevel: true,
ascii_only: true,
beautify: true,
max_line_length: 1000
},
preserveLicenseComments: true,
logLevel: 0
})
I'm certainly not an expert in this area, but I did manage to get this working for one of my projects, admittedly mainly by trial and error.
I found that I needed to make either/both of appdir and baseUrl be a directory which contained both my code and the library code - in your case, this would either be ./app/js or ./app (depending on whether you also wanted your templates combined).
I also supplied paths to the various library functions.
Having got it working I really ought to go back and see what was actually necessary, and what was cargo-cult coding. For now I have more pressing code to be writing...
For your interest I include my options: note I am optimizing from node.js via rjs.optimize(...).
var options = {
baseUrl: "./site/app",
appdir: "./site/app",
name: "js/main",
out: "main-built.js",
paths: {
jQuery: 'js/libs/jquery/jquery',
Underscore: 'js/libs/underscore/underscore',
Backbone: 'js/libs/backbone/backbone',
Handlebars: 'js/libs/handlebars/handlebars',
templates: 'templates'
}
};
I'm not expecting this to be the correct answer, but hopefully it will lead you somewhere useful.

Categories