Using r.js to optimize bower_components directly - javascript

I'm having trouble using r.js to optimize modules in the bower_components/ directory.
My basic project directory structure looks like this:
- bower_components/
- src/
- activities/
- client/
...and the r.js configuration lists the following details:
({
appDir: 'src',
baseUrl: 'client',
dir: 'out',
modules: [
{ name: 'scripts/main' },
/* (+ more) */
]
})
I'd like to optimize the file
bower_components/socket.io-client/dist/socket.io, which is outside the
baseUrl. As recommended in the "Common Pitfalls" section of the Optimizer
guide, I'm trying to
define a path for the file:
({
appDir: 'src',
baseUrl: 'client',
dir: 'out',
+ paths: {
+ 'socket.io': '../../bower_components/socket.io-client/dist/socket.io'
+ },
modules: [
{ name: 'scripts/main' },
/* (+ more) */
+ { name: 'socket.io' }
]
})
...but this yields the following error:
Running "requirejs:prod" (requirejs) task
{ [Error: Error: Module ID 'socket.io' has a source path that is same as output path: /home/mike/projects/cee/bower_components/socket.io-client/dist/socket.io.js. Stopping, config is malformed.
at /home/mike/projects/cee/node_modules/grunt-contrib-requirejs/node_modules/requirejs/bin/r.js:26000:39
]
originalError: [Error: Module ID 'socket.io' has a source path that is same as output path: /home/mike/projects/cee/bower_components/socket.io-client/dist/socket.io.js. Stopping, config is malformed.] }
It seems like the point of the path config indirection is so that the
optimizer will not attempt to create a file outside the output directory. At
the same time, this is clearly not happening. Am I doing something wrong? Or is
this not something r.js is capable of?

Related

Webpack not generating bundle since npm update

Some weeks ago I updated all my dependencies using npm ... --force and whatnot. Some may say this wasn't the greatest choice, but still...
I don't know exactly why, but since I updated my NPM dependencies, webpack doesn't generate my output bundle anymore, which it did before just fine.
The project is laid out as following
- app/
|- dist/
|- app-server/ (Node + Express)
|- app.js
|- ...
|- app-frontend/ (Vue + Bootstrap)
|- dist/ (HTML/CSS/etc)
webpack.config.js (Run from inside app-server/):
const nodeExternals = require('webpack-node-externals');
const CopyPlugin = require('copy-webpack-plugin');
module.exports = [
{
name: 'server',
entry: './app.js',
output: {
path: __dirname + '/../dist',
filename: 'app_bundle.js',
},
mode: 'production',
target: 'node', // in order to ignore built-in modules like path, fs, etc.
externals: [
nodeExternals({})
],
plugins: [
new CopyPlugin({
patterns: [{ from: '../app-frontend/dist', to: '../dist/frontend' }],
})
],
stats: {
colors: true,
hash: false,
version: false,
timings: false,
assets: false,
chunks: false,
modules: false,
reasons: false,
children: false,
source: false,
errors: false,
errorDetails: false,
warnings: false,
publicPath: false,
},
},
];
The logs only say:
Entrypoints:
app (434 KiB)
css/chunk-vendors.f6f30965.css
js/chunk-vendors.98eb6b3c.js
css/app.a6ef7e2c.css
js/app.4fd07954.js
Child server:
Built at: 06.10.2020 19:07:17
Entrypoint main = app_bundle.js
and no file gets generated. I tried chmod 775 dist/ to no avail. I re-cloned the repo, to no avail. I deleted the CopyPlugin part, to no avail.
Hey, I even got to the root directory of my Ubuntu and did find * | app_bundle.js -r and it didn't find anything besides logs that have this name in it, which upon opening, are the log presented above.
I'm scratching my head on this since yesterday.
Any help is greatly appreciated!
I eventually figured it out!
The problem was that I was shooting myself in the foot by adding these lines:
stats: {
errors: false,
errorDetails: false,
warnings: false,
}
Which basically meant that it just exited with error code 1, but without telling me the error.
I thought that these parameters were to disable the errors within the browser. Apparently I was wrong.
Once I set those above to true and running webpack again, I saw that it indeed had some errors.
In my case, the error was that I was creating files (under Windows) with the name (for example) orderController.js, but require them calling ../../OrderController, which is, as you may see, not exactly equal. My file has a o and the script contains a capital O, which under Windows worked just fine, but I forgot that Linux (the server the production runs on) is case-sensitive.
After fixing those errors, webpack ran just fine and generated my bundle at the specified output directory!

JS : karma rollup empty bundle

[UPDATE]
The original title of this post was : "Bad karma, lost data" and standed for the mind word play, much more for the rimes than for a real fact. So I decided to alter it, for the sake of correctness and courtesy.
[UPDATE]
Hi there, I've a very classical program directory strcture:
dist/
karam.conf.js
node_modules/
package.json
rollup.config.js
src/
fp/
list.js # imports maybe.js
matbe.js
test/
fp/
list.specs.js
maybe.specs.js
I'm trying to preprocess the tests with rollup. My karma.conf.js is just like :
# karma.conf.js
const buble = require('#rollup/plugin-buble')
const resolve = require('#rollup/plugin-node-resolve').default
// console.log({ resolve })
module.exports = function(config) {
config.set({
basePath : '',
files: [
{
pattern: 'src/fp/*.js', watched: true
},{
pattern: 'test/fp/*.specs.js', watched: true
}
],
watch: true,
preprocessors: {
'src/fp/*.js': ['rollup2'],
'test/fp/*.specs.js': ['rollup2']
},
rollup2Preprocessor: {
output: {
name: 'fptest',
format: 'iife'
},
plugins: [
buble(),
resolve()
]
}
});
}
When I start karma, with npm or from CLI with "karma start --log-level debug", I get 4 empty bundles and get the error message "Error during file loading or preprocessing
TypeError: output is not iterable".
So I could not test my program properly.
What's happening and how to fix that ?
Thanks for replies, Regards.
Looking at your module loader, I suggest using a karma plugin like karma-rollup-preprocessor to bundle your module before running tests. This will bundle and wire-up your modules properly for testing.
And you don't need to specify all your files under files array.
files: [
'test/**/*.js'
],

How to get node package consumer directory from node_modules?

I am trying to create a simple node module that creates a set of folders in the app that consumes it. I exported a simple createLayout function that creates the folders. I pushed my changes to git and did an npm i from another folder. Lets call the modules creator and consumer for the sake of explanation. When I try to call createLayout in consumer I am running in to several issues. I am in E:\ drive.
Below is the index.js in creator:
import {sync} from 'mkdirp';
export function createLayout(config) {
sync('./folder1');
}
And index.js in consumer:
var createLayout = require('creator').createLayout;
createLayout();
// with config createLayout({path: __dirname})
This results in creating a folder in E:\ not relative to consumer. So I tried including __dirname:
sync(__dirname + '/folder1');
Once again, this also creates a folder in E:\ not relative to consumer. I searched for bit like in various modules to see how they are doing when they are reading the config file, for instance webpack uses process.cwd. So I tried that too.
sync(process.cwd() + '/folder1');
Same, results in creating a folder in E:\ not relative to consumer. Then I tried to pass the __dirname or cwd through a config object.
// get __dirname from the `consumer` in config.path
sync(config.path + '/folder1');
But it ends up in following error:
Error: EPERM: operation not permitted, mkdir 'E:\'
I tried logging all the values in both creator and consumer:
console.log(__dirname, process.cwd(), config.path)
// creator: / / E:\projects\consumer
// consumer: E:\projects\consumer E:\projects\consumer E:\projects\consumer
I am using webpack with babel to pack the creator, plain js in consumer. I do not know what am I doing wrong. I am pretty new to nodejs ways of working.
Update
I am noticing that this is occurring only when I use webpack to build the creator. A simple module.exports works normally as anyone would expect. So I am including my webpack config file:
module.exports = {
entry: [
'./index.js'
],
output: {
filename: 'creator.js',
path: __dirname + '/dist',
library: 'creator',
libraryTarget: 'umd'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel'
}
]
},
externals: {
fs: 'fs'
}
};
Correct solution is adding this line in config:
target: 'node'
this will make webpack to ignore modules like fs and mkdirp and some other.
Now no longer need to specify externals.
Incorrect solution given before:
Just add mkdirp to externals and it will resolve you problem:
externals: {
fs: 'fs',
mkdirp: 'mkdirp'
}

Grunt & requirejs optimizer for a multi app project

I'm having issues getting Grunt to perform requirejs optimization on a project with the following structure:
static/js
|── apps
|── app.js
|── dash.js
|── news.js
... (many more 'app' files)
|── build
|── collections
|── libs
|── models
|── util
|── views
Each of static/js/apps/*.js should be compiled to static/js/build/*.js containing the relevant dependencies (eg. views/view1, libs/query etc).
This is currently being performed by a basic bash script:
JS_ROOT="static/js"
for f in ${JS_ROOT}/apps/*
do
FILE=$(basename -s .js ${f})
pushd .
cd ${JS_ROOT} && r.js -o baseUrl=. name=libs/require-min.js include=apps/${FILE} out=build/${FILE}.js
popd
done
I'm attempting to move to a Grunt-based optimization, with the following in Grunt.js:
requirejs: {
compile: {
options: {
appDir: 'static/js/',
baseUrl: './apps/',
dir: 'static/js/build/',
modules: [
{
name: 'app',
}
]
}
}
}
Running generates the following error:
>> Tracing dependencies for: app
>> Error: ENOENT, no such file or directory
>> 'static/js/build/apps/libs/jquery.js'
>> In module tree:
>> app
I can clearly see what the problem is, but am failing to figure out how to indicate that the dependencies in each static/js/apps/*.js file are in static/js/ not static/js/build
In addition to this, I'm assuming that the modules block containing name: 'app' should be outputting the compiled file static/js/build/app.js from the contents of static/js/apps/app.js.
Without creating an additional module block for each file in static/js/apps, how can I compile each of the files into their relevant static/js/build/*.js file?
Update 1
So the following in my Gruntfile compiles static/js/apps/app.js successfully into static/js/build/app.js:
requirejs: {
compile: {
options: {
baseUrl: 'static/js/',
include: './apps/app.js',
out: 'static/js/build/app.js',
}
}
}
The next step being to compile static/js/apps/*.js into static/js/build/*.js without having to define each individually...
Update 2
Modifying the above to:
requirejs: {
compile: {
options: {
baseUrl: '../',
include: './apps/<%= appFile %>',
out: 'static/js/build/<%= appFile %>',
}
}
}
And creating the task:
grunt.registerTask('buildrjs', function() {
var dir='static/js/apps/';
grunt.file.setBase(dir);
var files = grunt.file.expand(['*.js']);
files.forEach(function(filename) {
grunt.log.write('Compiling '+filename+'\n');
grunt.config.set('appFile', filename);
grunt.task.run('requirejs:compile');
});
});
Almost gets me to the solution. The tasks runs through each file in static/js/apps/ and passes the filename into grunt.config.set('appFile', filename);. The output of the task outputs Compiling app.js Compiling news.js... etc, however afterwards the actual requirejs:compile tasks runs over & over on the last file in the static/js/apps/ directory, rather than each individual file. An async issue?
Solved, by passing multiple sets of options to the requirejs task, thanks to this article for the final pointers I needed:
module.exports = function(grunt) {
var files = grunt.file.expand('static/js/apps/*.js');
var requirejsOptions = {};
files.forEach(function(file) {
var filename = file.split('/').pop();
requirejsOptions[filename] = {
options: {
baseUrl: 'static/js/',
include: './apps/'+filename,
out: 'static/js/build/'+filename
}
};
});
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
requirejs: requirejsOptions,
});
};
Then the ['requirejs'] task can be run as normal and will output the appropriate compiled .js file as per each of the options: {} blocks that were specified in requirejsOptions, eg:
grunt.registerTask('default', ['requirejs']);
You need to change baseUrl to static/js from apps in requirejs build config. As currently baseUrl is pointing to apps directory, require is trying to search dependency files in apps directory. If you change the baseUrl to static/js it will find those dependency files.
requirejs: {
compile: {
options: {
appDir: 'static/js/',
baseUrl: 'static/js',
dir: 'static/js/build/',
modules: [
{
name: 'app',
}
]
}
}
}

Require.js - Shared r.js config not using correct 'paths' values

I am using a 'mainConfigFile' between my development require.js environment and the r.js build tools—much like the setup in the Require.js multipage example. The modules require and load fine in development, but when I try to run the same config file through r.js it searches for module paths that are one directory higher. (For example. it searches for the build version of backbone.js in build/backbone.js when it should be looking in build/vendor/backbone.js).
Here is my r.js build json config:
{
baseUrl: "js/lib",
mainConfigFile: 'js/lib/common.js',
dir: 'build',
paths: {
'stripe': 'empty:'
},
modules: [
{
name: "common",
include: [
'underscore',
'backbone',
'backbone.validation',
'vendor/spin',
'vendor/transit',
'globals'
]
},
{
name: 'product',
exclude: [ 'common' ]
}
],
optimize: 'none'
}
Here is my common.js shared config file located in js/lib/common.js
requirejs.config({
baseUrl: '/js/lib',
paths: {
'config': 'empty:',
'inline': 'empty:',
'stripe': '//js.stripe.com/v1/stripe',
'vendor': '../vendor',
'underscore': '../vendor/underscore',
'backbone': '../vendor/backbone',
'backbone.validation': '../vendor/backbone.validation',
'text': '../vendor/text'
}
});
Finally, here is the product.js module located in js/lib/product.js which is loaded from data-main during development.
require(['./common'], function() {
require(['./product/main', 'inline']);
});
The interesting problem is when I remove "../vendor/" from each of the config values—except the 'vendor' property itself—the r.js build is successful and the development data-main is unable to load the correct files. Surely I'm overlooking some config setting.

Categories