rollup equivalent of "browserify -r" - browserify

I need to force some modules into my bundle, as they are required dynamically through some code like below:
var moduleName = "someModule";
var myModule = require(moduleName);
I was using browserify to bundle this (through browserify -r or the API equivalent).
I am trying to switch to rollup and I don't figure out how to do this with rollup. Basically, I just want to force some modules into the bundle, and make them available globally through the require statement.

I think the key here is to use the new ES6 module syntax as described in the Rollup documentation. This will also give Rollup the possibility to apply features like chunking and tree-shaking.
Another important thing is to make it explicit what might get imported. By that I mean to use statements like 'import('./module1.js')' instead of 'import(some_variable)'. It is hard for Rollup to figure out all possible contents of the variable which gets used in the import. Therefore I would use explicit file names here but wrap everything in some kind of if/else condition.
Consider the following example:
File ./src/main.js:
let num = Math.random() * 10;
let condition = Math.round(num % 3);
let mod;
if (condition === 1) {
import('./module1.js').then((module)=> {
log(module);
});
} else if (condition === 2) {
import('./module2.js').then((module)=> {
log(module);
});
} else {
import('./module3.js').then((module)=> {
log(module);
});
}
function log(module) {
mod = module;
console.log(mod.test());
console.log('Done');
}
File ./src/module1.js:
function test() {
return 'This is 1!';
}
export { test };
The files module2.js and module3.js are the same like module1. The only difference is that they log 'This is 2!' and 'This is 3!'.
The Rollup config looks like this:
const production = !process.env.ROLLUP_WATCH;
export default {
inlineDynamicImports: true,
input: 'src/main.js',
output: {
dir: 'public/',
format: 'esm',
sourcemap: true
}
};
If you run 'rollup -c' then there will be one file './public/main.js'. This bundle will include all three modules. Usually Rollup would create main.js and three chunks. By using the setting 'inlineDynamicImports=true', Rollup puts everything in one file.
You can also change the format in the Rollup config to 'iife' (or amd, cjs, umd) if you want to.

Related

why read tsconfig.json using readConfigFile instead of directly requiring the path of tsconfig.json?

Upon investigating create-react-app's configuration, I found something interesting.
// config/modules.js
...
if (hasTsConfig) {
const ts = require(resolve.sync("typescript", {
basedir: paths.appNodeModules,
}));
config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config;
// Otherwise we'll check if there is jsconfig.json
// for non TS projects.
} else if (hasJsConfig) {
config = require(paths.appJsConfig);
}
...
Unlike reading jsconfig.json file using direct require(paths.appJsConfig), why is here using resolve.sync and ts.readConfigFile to read the tsconfig.json?
...
if (hasTsConfig) {
config = require(paths.appTsConfig)
// Otherwise we'll check if there is jsconfig.json
// for non TS projects.
} else if (hasJsConfig) {
config = require(paths.appJsConfig);
}
...
If I change the code like just above, the result is same. (at least the console output is same.)
There must be a reason why create-react-app using such a complicated way to read the typescript config file.
Why is that?
The ts config reader is a bit smarter than simply reading and parsing a json file. There's two differences I can think of right now:
in tsconfig files, you can use comments. JSON.parse will throw an exception because / is not an allowed character at an arbitrary position
ts config files can extend each other. Simply parsing a JSON file will ignore the extension and you'll receive a config object that doesn't represent what typescript actually uses.

Loading custom module base on context in server side SuiteScript 2.0

I'm trying to load my custom module base on the condition.
CustomModule.js
define([], function(){
export {
run: function(){ log.debug('run in CustomModule' }
};
}
And here is my user event script
userevent.js
define(['N/record'], function(record){
...
var moduleName = record.getValue('custom_module_name'); // will return CustomModule.js
require([moduleName], function(customModule){
customModule.run();
});
});
But I got following error
{
type: "error.SuiteScriptModuleLoaderError",
name: "INCORRECT_SUITESCRIPT_CONFIGURATION",
message: "Incorrect SuiteScript configuration for module: CustomModule.js",
}
When I using preload like define(['CustomModule.js'), function(customModule){...})
is working, but this might not suitable for our scenario.
Any suggestion?
So the way you would call a custom module would be (sample snippets below):
CustomModule.js [Code in file cabinet]
define([], function() {
// You can have multiple functions
function testFunction() {
log.debug("Run in CustomModule");
return 123;
}
return { // Return all your functions here
testFunction: testFunction
};
});
And the way you would call the custom module functions in other scripts would be:
Sample User Event Script:
/**
* #NApiVersion 2.x
* #NScriptType UserEventScript
* #NModuleScope SameAccount
*/
define(['./CustomModule.js'], function(customModule) {
.....
function sampleFunction(customerId, recId, invNumberCounter) {
var storeNumber = customModule.testFunction(); // value of 'storeNumber' will be 123
}
.....
});
Additional Important Note:
When writing library scripts (custom modules), have the client-side supported modules in a different script and server-side supported modules in a different script.
This is because, if you incorporate a library script that has a module which is supported only by server-side scripts (eg. N/task module) into a client script, an error would be thrown saying that the module is not supported in this scrpt.
Hope this helps.

How to import GraphQL query as a string instead of an object

I created a .gql file for my query and I'm importing it like this:
const query = require("#/hello.gql");
However, if I log the query variable to the console, it shows an object, not a string. What can I do so that my imported query is just a string?
When querying your server using apollo-client, the provided query parameter has to be an object of the type DocumentNode, which is an AST representation of the query. In other words, if you use apollo-client, you can't just pass it a query as a string, you have to parse it first. This is commonly done using the graphql-tag library. It can also be done automatically through webpack by utilizing a loader like graphql-tag's loader or graphql-loader. If you utilize a loader like that, then any .gql files you import will automatically be parsed into DocumentNode objects for you.
If you're not using apollo-client, there's no need to utilize those loaders. If you still want to store you queries in separate files and import them as strings, you should utilize a different loader, for example, raw-loader.
Because, you are only importing the query, not using it.
You can use apollo to use that query like this
const yourQuery= require("#/hello.gql");
data(){
return {
queryResponse: []
}
}
apollo: {
queryResponse: {
prefetch: true,
query: yourQuery
}
}
Whit this, you are fetch the query and save the response in queryResponse
Now raw-loader is deprecated, you can load them like this.
In the webpack config
module: {
rules: [
{
test: /\.gql/,
type: "asset/source",
},
],
},
Then import
import myGraphQlQuery from "myGraphQlQuery.gql"

How to publish alpha npm module without confusing the community?

Given an useless pet node module.
./node_modules/salutations.js :
var cl = function (msg) { console.log(msg) }
var hi = function () { cl("Hi !") }
var seeYa = function () { cl("SeeYa !") }
exports.hi = hi;
exports.seeYa = seeYa;
./script.js :
var salutations = require('salutations')
salutations.hi(); // returns: "Hi !"
salutations.seeYa(); // returns: "SeeYa !"
./package.json
{
"name": "NodeSalutations",
"version": "0.0.1",
dependencies: {}
}
Given its creation sole purpose was to learn about the creation , then publication on npm.org of a minimalist node module.
Given there is nothing valuable on this module, so I don't want to set up a private account.
Is there a way to publish, test, then remove discretely the module on npm, without polluting npm.org ?
Edit : I did read npmjs.com's publish, unpublish, registry and scope.
You could just upload it to NPM.org and then deal with clean up later, Considering the scope of the module I'm sure no one would get invested enough to mind a removal/change.
Your other option is to host your own NPM repository for testing (this is what I would do) using something like sinopia

dojo.requireIf does not allow local variables

I've been trying to use dojo.require(If) with a local variable to dynamically load a module on a page based on a condition.
// note: dojo v1.4
djConfig = {
debugAtAllCosts: true
};
Example 1 (does not work):
(function() {
var nameOfClass = "Two";
dojo.require("my.namespace." + nameOfClass);
dojo.addOnLoad(function() {
var oneOrTwo = new my.namespace[nameOfClass]();
});
}());
Error: ReferenceError: nameOfClass is not defined.
Example 2 (does not work):
(function() {
var nameOfClass = "Two";
dojo.requireIf(nameOfClass == "One", "my.namespace.One");
dojo.requireIf(nameOfClass == "Two", "my.namespace.Two");
dojo.addOnLoad(function() {
var oneOrTwo = new my.namespace[nameOfClass]();
});
}());
Error: ReferenceError: nameOfClass is not defined.
Example 3 (works):
(function() {
window.nameOfClass = "Two";
dojo.requireIf(window.nameOfClass == "One", "my.namespace.One");
dojo.requireIf(window.nameOfClass == "Two", "my.namespace.Two");
dojo.addOnLoad(function() {
var oneOrTwo = new my.namespace[nameOfClass]();
});
}());
For some reason, it appears as though require and requireIf only allow global variables inside them. Is that a current limitation, or am I just doing something wrong?
Update 1:
Therefore, if I understand you (#Maine, #jrburke) correctly, this is a limitation of the debugAtAllCosts? If the above code is built as cross-domain (adding the xd file prefix / suffix) and is executed -- it will work as expected?
If that is the case, then what is the proper way of locally testing code that will be executed as cross-domain, without making the actual build?
That also makes me question the motivation for pre-parsing the dojo.require(s). If the loader_xd will not (or rather can not) pre-parse, why is the method that was created for testing/debugging doing so?
Update 2:
Since the two questions in the Update 1 above are not closely related to this one, I've moved them out into a separate discussion.
This is because requireIfs are parsed with regexps as the very first thing, and executed before the normal program flow.
If you'll grep Dojo source for requireIf, you should find this kind of lines handling it (loader_xd.js):
var depRegExp = /dojo.(require|requireIf|provide|requireAfterIf|platformRequire|requireLocalization)\s*\(([\w\W]*?)\)/mg;
The condition is then executed with eval in global scope, and not as a part of normal flow.
To clarify more of what Main said, this is an issue with the XD loader in Dojo. debugAtAllCosts: true uses the XD Loader. If you just use the normal Dojo loader without debugAtAllCosts, it is not an issue. Also, attaching the module module name as a property on a publicly visible module would also avoid the issue.