I have tried harder and harder to understand the difference between bundle and bundle SFX from the documentation of JSPM and system.js. But I was unable to get the difference. I haven't used jspm till now but I want to use it in my current project.
Another question - If I am importing different modules in a.js and different modules in b.js, where both a.js and b.js are mutually exclusive, can I bundle both of them in a single file c.js using JSPM?
Please help, I would really appreciate it.
To create an output distributable script file that can be included
entirely on its own independent of SystemJS and jspm, we can use
bundle-sfx.
jspm bundle-sfx app/main.js app.js app.js
contains a micro-loader
implementation (1.4KB gzipped), converts all module formats into ES5
(including compiling ES6), and maintaining bindings and circular
references as with normal bundles.
Source: http://jspm.io/docs/production-workflows.html
Related
I have a library (ES6) which is composed on many sub-modules, say
- package.json
- lib
- my_package
- file1.js
- file2.js
- sub_module1
- file3.js
- file4.js
I currently do imports like this (all inside my package - using file resolution to find, not node_modules resolution):
import {func1} from 'lib/my_package/file1'
import {func3} 'lib/my_package/sub_module1/file3'
So, in practice I have many files across sub-directories.
I am now trying to package and publish my library, which will be installed under node_modules.
It seems to me that the node resolution algorithm (when behind node_modules) only allows for a single entry point (and there is nothing rollup can do about that)
I would like to be able to include many sub directories and files and for them to be resolved individually.
As far as I understand I have to include a single toplevel file that has all the export from machinery. I can only import that single top level file.
This means having to manually create that file. It also means losing the all the sub-module name structuring that comes from the directory structure.
I was wondering: is there any way one can import any other file from a node_module directly?
Node's resolution algorithm only resolves the first part of a module source, so if someone does this...
var foo = require('your-library/subdir/foo.js');
...then Node (or Browserify/Webpack/rollup-plugin-node-resolve) will correctly resolve that to
/path/to/project/node_modules/your-library/subdir/foo.js
The tricky part is that you want to author JavaScript modules, but if someone is using your library in Node then they need CommonJS modules. Rollup can't help you here — you would need to do a one-to-one ESM->CJS conversion for each module. So that means either using Babel, or authoring CommonJS modules in the first place.
I was going through Angular2 quickstart tutorial with Javascript and Typescript as well, In javascript version I observed that components and modules are first assigned to a variable (window.app which I understood as some global variable that can be accessed across js files or script blocks) and that is fine. Coming to type script version just export and import were used, I tried to analyze the generated javascript code but understood nothing. Can some one explain me how this export and import works in Tyepescript.
Import and export in typescript are explained well by the documentation here https://www.typescriptlang.org/docs/handbook/modules.html.
Like toskv said in his comment, how those statements in your TypeScript files get transpiled into statements in your JavaScript files depends largely on the module system you set up in your tsconfig.json file.
For example, setting "module": "commonjs" will cause the TypeScript compiler (tsc) to transform your import/export statements into essentially node.js-style require() statements. This documentation has a few simple, but helpful, examples of how node.js modules work: https://nodejs.org/api/modules.html.
Using a setting of "systemjs" instead of "commonjs" will make TypeScript translate your import/export statements into a format that SystemJS understands, of which I am no expert.
This process is further complicated by the fact that Angular 2 projects also require build steps that take the transpiled JavaScript files and turn them into packaged "bundles." These bundled files are (depending on your configuration settings) concatenated, minified, and perhaps even uglified. So looking at the final javascript code that is run is really not helpful, as it was not written by humans.
For example, the Webpack build system (google webpack.js) takes require() statements it finds in JavaScript code and does some magic to wrap each module in its own __webpack_require__ function, which allows the build system to take your whole project file structure and bundle it in to one or several JavaScript files which still maintain their dependencies on each other.
In other words, by the time you look at the production JavaScript code, it's not meant to be intelligible by human readers. The flow can be simply represented by TS Source Code > TS Transpilation into JS Code > Module/Dependency Build Steps into Production JS Code.
TL;DR TypeScript doesn't actually handle the module importing/exporting. During transpilation, it converts those statements into statements other module systems (node.js or SystemJS) can understand, which are in turn converted into production code for serving an Angular 2 application.
I'm using Converse.js and it's prebuilt into the RequireJS/AMD syntax. Including the file from a CDN you could use it like require(['converse'], function (converse) { /* .. */ }). How is it possible to use this with webpack? I would like to bundle converse.js with my webpack output.
I have the file on disk, and want to import it like
import converse from './converse.js';
converse.initialize({ .. });
Webpack picks up the file and bundles it correctly, although it's not useable yet as it throws 'initialize is not a function'. What am I missing?
I suspect the way their bundle is built will not work correctly with how Webpack evaluates modules in a limited context.
From their builds, taking the built AMD module via NPM without dependencies should be parsable by Webpack and it will enable you to provide the dependencies to avoid dupes in the final output.
If all else fails, using the script-loader will evaluate the script in the global context and you'd get the same experience as if you'd have followed their usage guidelines to reference it from a CDN, just don't forget to configure the globals for your linter.
Currently my process for building is:
Write lots of typescript files with ES6 module syntax
Generate an index.ts which re-exports all modules from one point
Compile to CommonJS + System
Output Descriptor/Typing files
This results in an index.js file which re-exports all the internal files without the developer consuming it needing to know about it, as well as a lot of d.ts files which mirror the file structure.
Now this works, but if I were to take this approach to the browser I would need to webpack up all the js or it would be a http request nightmare pulling in all the individual files. Currently this library would be consumed as a dependency for other libraries, so it is not an end point for logic or anything it is a module/library.
Now the main question is with webpack I know I can load TS in and get a commonJS module out, however I cannot find any way to generate d.ts files with webpack. So is there a way for me to use webpack as the compiler/packager in this scenario and have an output my-lib.js and my-lib.d.ts rather than the current approach which yields lots of individual files.
== Extra Clarification on Use Case ==
Just to try and make sure everyone is on the same page here when I say it is a library that would be re-used what I mean is that this is something that would be loaded via npm or jspm or something as a module dependency for other modules.
So for example let us pretend jquery doesn't exist and I am going to create it but write it in typescript for other developers to consume in both JS and TS. Now typescript outputs both js files and d.ts files, the js files are to be used as you would expect, but the d.ts files explain to other typescript files what the types contained within the library are.
So assuming I have developed jquery in TS as listed above, I would then want to publish this output (be it created by webpack or tsc) on npm/jspm/bower etc. So then others can re-use this library in their own projects.
So webpack typically is used to package an "application" if you will, which contains logic and business concerns and is consumed directly as an entry point to a larger set of concerns. In this example it would be used as a compilation and packaging step for a library and would be consumed via var myLib = require("my-lib"); or similar.
Generating the .d.ts files is not related to webpack. With webpack you can use either ts-loader or awesome-typescript-loader. Both of them make use of tsconfig.json. What you need to do is to add declaration: true in your tsconfig.json.
I'd also suggest you to take a look at typescript-library-starter. You'll find how's set up there, including UMD bundle and type definitions :).
So I know how to require and export modules in ES6. But for frameworks like Aurelia, the docs say that you require aurelia like so:
import {LogManager} from 'aurelia-framework';
Do I have to place a JS file named aurelia-framework in the folder where the JS file I'm executing it from resides, or does the import function work similiar to the require function in NodeJS/CommonJS?
According to this article ES6 modules spec only deals with loading modules that are present in the file path. Downloading these files (via NPM or by other means) is outside of scope of ECMAScript 6 modules spec. Nothing is said in the spec about supporting npm package includes (traversing the directory structure down to the /, one directory at a time, looking for a package.json file and then searching within the node_modules directory where package.json file is found). So while the import syntax is similar to commonJS style, the whole magic of looking for modules in the node_modules directory is not included.
So for your example to work, aurelia-framework must be a javascript file somewhere in your file system and it should contain an exports statement.
import {LogManager} from 'aurelia-framework'; // ./aurelia-framework.js
import {LogManager} from '../libs/aurelia-framework'; // ../libs/aurelia-framework.js
with Aurelia, you can install dependent libraries using jspm. you can see an example of that here. jspm will get the packages for you and bring them into subfolders in your project. jspm uses an index (stored in config.js) to know where to locate the files (similar to how requirejs, but works for amd, commonjs, and es6 modules).
there is also an example of using the aurelia libraries with requirejs amd loader. this example uses a bundle of aurelia libraries generated by r.js as shown here