I have a ClojureScript project that I was compiling in "dev" mode, with no compiler optimizations. I would "run" it like this, from HTML, a described in the quick start docs.
<script src="/js/out/goog/base.js"></script>
<script src="/js/out/main.js"></script>
<script> goog.require("myapp.mymodule"); </script>
The main.js file is the one generated by the ClojureScript compiler, from .cljs source files.
Now I have a second profile in my Leiningen project that enables advanced compiler optimizations. As expected, main.js changes to include a lot of obfuscated Javascript. But now the require line above fails:
Error: goog.require could not find: myapp.mymodule
I also tried marking one of my functions with :export:
(defn ^:export foo [] ...)
But the docs don't mention where that symbol will be, and I don't see it on window or anywhere else.
So, how does the HTML call into the compiled ClojureScript to get the program started?
Here are the relevant sections of my project.clj
:cljsbuild {
:builds {
:app {
:source-paths ["src/main/clj"]
:compiler {
:output-to "target/resources/public/js/out/main.js"
:output-dir "target/resources/public/js/out"
:asset-path "/js/out"
}
}
}
}
...
:profiles {
:uberjar {
:hooks [leiningen.cljsbuild]
:omit-source true
:cljsbuild {
:builds {
:app {
:compiler {:optimizations :advanced
:pretty-print false}
}
}
}
}
And to compile with the optimizations I ran:
lein with-profile uberjar cljsbuild once
You need to add some compiler options, like :output-to and :source-path.
You can find the list of options at https://clojurescript.org/reference/compiler-options.
If you want to see what a minimal production build looks like, create a new empty project using lein new cljsbuild-template <project-name>
Related
I am trying to include bootstrap in my OJET project where I use ojet v6 library.
I got an error saying ojmodule failed due to "popper is required".
What I have Tried
I have added the popper.js in lib folder.
I have included the lib in main.js file inside require.js configPath array.
requirejs.config({
// Path mappings for the logical module names
paths:
//injector:mainReleasePaths
{
'popper' : 'libs/popper/popper.min' ,
'bootstrap' : 'libs/bootstrap4/js/bootstrap.min',
//other libs goes here
Added the "popper" reference in shim object of main.js
shim: {
'jquery': {
exports: ['jQuery', '$']
},
'Popper' : {
exports : ['Popper', 'popper']
}
}
added the popper reference in an ojet module. by
define(['ojs/ojcore', 'knockout', 'appController','popper','bootstrap'],
function (oj, ko, app, popper,bootstrap) {
Still get an error failed to load ojet module "popper is needed by require.js". Please help or suggest any edit.
Bootstrap 4 uses popper.js and jquery as its dependency. It should be loaded before bootstrap. As I can see you have added in shim and assuming that the path provided in the require.config is correct It should work;
If it is not working you can have a workaround like instead of adding the dependency separately to the project add the bootstrap bundle directly.
requirejs.config({
// Path mappings for the logical module names
paths:
//injector:mainReleasePaths
{
'jquery': 'libs/jquery/jquery-3.3.1',
'bootstrap' : 'libs/bootstrap4/js/bootstrap.bundle.min',
Note the bootstrap.bundle.min.js contains popper but not jquery. So you need to load jquery before bootstrap.
I tried to include underscore.js and followed below steps:
npm i underscore.js, we can install any module because it runs on node
modify path_mapping.json:
"underscore": {
"cdn": "3rdparty",
"cwd": "node_modules/underscore",
"debug": {
"src": "underscore.js",
"path": "libs/underscore/underscore.js",
"cdnPath": "underscore/underscore.1.0"
},
"release": {
"src": "underscore.min.js",
"path": "libs/underscore/underscore.min.js",
"cdnPath": "underscore/underscore.1.0"
}
}
modify main.js
'underscore': 'libs/underscore',
use in viewModels:
define([
"require", "exports", "knockout", "ojs/ojbootstrap", "ojs/ojconverterutils-i18n", "ojs/ojarraydataprovider", "ojs/ojcolor", "ojs/ojconverter-datetime", "underscore","ojs/ojknockout", "ojs/ojbutton", "ojs/ojinputtext", "ojs/ojcollapsible", "ojs/ojinputnumber", "ojs/ojradioset", "ojs/ojcheckboxset", "ojs/ojselectcombobox", "ojs/ojselectsingle", "ojs/ojdatetimepicker", "ojs/ojswitch", "ojs/ojslider", "ojs/ojcolorspectrum", "ojs/ojcolorpalette", "ojs/ojlabel", "ojs/ojformlayout", "ojs/ojlabelvalue","ojs/ojaccordion","ojs/ojactioncard"
],
function (require, exports, ko, Bootstrap, ojconverterutils_i18n_1, ArrayDataProvider, Color, ojconverter_datetime_1,_) {
function EmployeesViewModel() {
_.each([1, 2, 3], console.log);
var self=this;
self.logMsg = ko.observable("none");
self.actionHandler = (event) => {
this.logMsg("Action handler invoked - " + event.currentTarget.id);
};
}
return EmployeesViewModel;
});
instead of adding bootstrap.min.js add bootstrap.bundle.min.js to your require path.
I am trying to generate source-maps with a gulp task. I'm transpiling my code with Babel, and I would like to be able to use the debugger from VS Code. I don't know a lot about source-maps, and my way of determining if they are valid or not is to attempt using the debugger with breakpoints (if it stops on the breakpoints, then it works).
Here is my script:
// src/main.js
const i = 1;
const n = 2*i; // breakpoint on this line
console.log(n);
And here is my configuration for the debugger:
//.vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}/dist/main.js"
}
]
}
The command npx babel src --out-dir dist --source-maps transpiles my code and a .js.map file is created in the dist folder.
Executing the debugger configuration from above works as intended. The debugger stops on the breakpoint.
The command npx babel src --out-dir dist --source-maps inline transpiles my code and the source maps are embedded within the .js output file.
Executing the debugger configuration from above also works as intended. The debugger stops on the breakpoint.
This shows that my debugger configuration should be working for both inline and external source maps.
I created the following Gulp task for the transpilation of my code.
import {dest, src} from "gulp";
import babel from "gulp-babel";
import sourcemaps from "gulp-sourcemaps";
function transpile() {
return src("src/**/*.js")
.pipe(sourcemaps.init())
.pipe(babel())
.pipe(sourcemaps.write(
".",
{
includeContent: false,
sourceRoot: "../src"
}))
.pipe(dest("dist"));
}
export {transpile};
The command npx gulp transpile executes this task and a .js.map file is created in the dist folder.
Executing the debugger configuration from above works as intended. The debugger stops on the breakpoint.
I then edited the Gulp task above so that it would give me inline source maps:
import {dest, src} from "gulp";
import babel from "gulp-babel";
import sourcemaps from "gulp-sourcemaps";
function transpile() {
return src("src/**/*.js")
.pipe(sourcemaps.init())
.pipe(babel())
.pipe(sourcemaps.write())
.pipe(dest("dist"));
}
export {transpile};
The command npx gulp transpile executes this task and the source maps are embedded in my output file.
However, the debugger doesn't stop on the break point.
I've not been able to understand why so far.
Since this is the only case where the debugger doesn't work, I believe the debugger is not the source of the problem. It must be linked to the source map.
Any idea?
Thanks a lot!
I'm using Gulp and the main-bower-files to bundle my bower dependencies.
I need to ensure that jQuery is included before AngularJS, but since the Angular bower package does not actually depend on jQuery it is included after.
Is there a way to push jQuery to the top of source list or override Angular's dependency so it does require jQuery?
I tried using the gulp-order plugin to do this but it messes up the original order of the remaining files:
gulp.task('bower', function () {
var sources = gulp.src(mainBowerFiles(['**/*.js', '!**/*.min.js'])); // don't include min files
return sources
// force jquery to be first
.pipe(plugins.order([
'jquery.js',
'*'
]))
.pipe(plugins.sourcemaps.init())
.pipe(plugins.concat('libs.min.js'))
.pipe(plugins.uglify())
.pipe(plugins.sourcemaps.write('./'))
.pipe(gulp.dest(config.output))
.pipe(plugins.notify({ message: 'Bower task complete' }));
});
You can override angulars dependencies in your project bower.json:
https://github.com/ck86/main-bower-files#overrides-options
{
...
"overrides": {
"angular": {
"dependencies": {
"jquery": "~1.8"
}
}
}
}
I haven't used main-bower-files but one trick I can think of is to just include the jquery file directly and don't load it in the main bower files array, e.g.
var glob = ['/path/to/jquery.js'].concat(mainBowerFiles(['**/*.js', '!/path/to/jquery.js']));
var sources = gulp.src(glob);
As the question states. I know gulp-uglify can uglify with a simple:
gulp.src('filename')
.pipe(uglify())
Is there a way to tell it to strip out console.log statements too?
Yes there is!
As gulp-uglifyjs documentation mentions you can pass extra options ( gulp-uglifyjs documentation):
uglify([filename], [options])
All available options can be found on the compressor UglifyJS documentation page. From that 'drop_console: true' should help:
uglify([filename], {
compress: {
drop_console: true
}
})
Much better still: you can use the specialized gulp plugin: gulp-strip-debug. It doesn't only strip out console statements, but also alerts and debugger statements.
Strip console, alert, and debugger statements from JavaScript code with strip-debug
install it using:
npm install --save-dev gulp-strip-debug
and use it like:
var gulp = require('gulp');
var stripDebug = require('gulp-strip-debug');
gulp.task('default', function () {
return gulp.src('src/app.js')
.pipe(stripDebug())
.pipe(gulp.dest('dist'));
});
With gulp-uglify (not gulp-uglifyjs) you can remove arbitrary code by using a strategy similar to compilations constants with the compression configuration (Link goes to gulp-uglifyjs, but should be the same for gulp-uglify):
.pipe(uglify({
compress: {
global_defs: {
"DEBUG": false
}
}
}))
And then in your code write something like
if (DEBUG)
{
console.log("Application started...");
//...
}
if you set DEBUG in global_defs to true, gulp-uglify will remove the conditional but leave the inner branch. In case DEBUG is set to false, it will remove both.
drop_console as in Fill's answer does not seem to be supported in gulp-uglify.
How should I be using requirejs-text which is installed via bower? I am supposed to put it in baseUrl but wonder if I could use it from components/requirejs-text/? Whats the best practice?
Define the path to the plugin in the config:
requirejs.config({
paths: {
"text" : "components/requirejs-text/text"
}
},
And use it in your module as documented on https://github.com/requirejs/text:
require(["some/module", "text!some/module.html", "text!some/module.css"],
function(module, html, css) {
//the html variable will be the text
//of the some/module.html file
//the css variable will be the text
//of the some/module.css file.
}
);
You can use also technically use the plugin without the path definition in the requirejs.config, but this is propbably not best practice:
require(["your_path_to_the_plugin_from_baseurl/without_js_at_the_end!some/textfile"],
function(yourTextfile) {
}
);
in PROJECT_APP/bower.js add this line under the dependencies section:
"requirejs": "~2.1.8",
"requirejs-text":"~2.0.10", // this is new
"qunit": "~1.12.0",
then run bower install, it should install this plugin and display at the end a path such as requirejs-text#2.0.10 vendor/bower/requirejs-text (depends on your configuration).
Finally, in the config.js file, add this line under
require.config({
paths: {
// Make vendor easier to access.
"vendor": "../vendor",
// Almond is used to lighten the output filesize.
"almond": "../vendor/bower/almond/almond",
// add the requirejs text plugin here
"text" : "../vendor/bower/requirejs-text/text",
// Opt for Lo-Dash Underscore compatibility build over Underscore.
"underscore": "../vendor/bower/lodash/dist/lodash.underscore",
// Map remaining vendor dependencies.
"jquery": "../vendor/bower/jquery/jquery",
"backbone": "../vendor/bower/backbone/backbone"
}
});
Then to use it, simply require it, in this case you can access it with the template variable
define([
// These are path alias that we configured in our bootstrap
'app', // general app variables
'jquery', // lib/jquery/jquery
'underscore', // lib/underscore/underscore
'backbone', // lib/backbone/backbone
'text!templates/books.html' // use the plugin to import a template
], function(app,$, _, Backbone, template){ // don't forget to define it !
This is how I have install requirejs-text using bower
In your project's bower.json file:
{
"name":"{{YOUR PROJECT NAME}}",
"version":"{{YOUR PROJECT VERSION}}",
"dependencies":{
"requirejs-text":"2.0.6"
}
}