it may sounds strange, but when I change the module name in my application, webpack changes the bundle output and makes it wrong. I have windows, it means that module paths should be case insensitive and the bundles must be the same all the time. Webpack shows me that some modules have ambiguous names and it can affect if you are using case-sensitive OS, but nevertheless the bundle works correct.
Then I fixed by changing the names in require from lower-case component to uppercase Component and after that webpack begins making invalid bundle, and there are a lot of diffs if you compare these two output bundles. My questions are: why does webpack behave different with case-sensitive names in case-insensitive environment and how to fix it? Maybe it changes the modules order or something like this.
P.S. The app is big: ~2.5 mb.
P.S.S. The problem is in inheritance. I use TypeScript and the error is that I try to extend from undefined.
Thanks!
why does webpack behaves different with case-sensitive name in case-insensitive environment
The true enviroment for webpack is the web and the web is case sensitive. Also it's probably just ordering e.g. alphabetically and that will change the ordering with changing names.
The problem is in inheritance. I use TypeScript and the error is that I try to extend from undefined
You might have a circular reference in there. The fact that it worked before is conincidental (e.g. the ordering by file names satisfied what was expected).
Fix
Remove the circular reference. E.g. use atom-typescript to find it : https://github.com/TypeStrong/atom-typescript/blob/master/docs/dependency-view.md#circular
Related
What does HashedModuleIdsPlugin do?
From Webpack docs:
This plugin will cause hashes to be based on the relative path of the module, generating a four character string as the module id. Suggested for use in production.
After reading it couple of times, I still can't understand why and when to use it and how it is related to the way I define a name to each bundle in output section:
filename: '[contenthash].[name].js',
I understand it this way, webpack 4.3 added contenthash, but before that, you can use HashedModuleIdsPlugin, I am not quite sure.
https://github.com/webpack/webpack/releases/tag/v4.3.0
By default, Webpack will create a list of modules (all the imported packages you have, as well as project files) and this list will be an array. The "module ID" (the pointer to the actual module code) will be the array index.
HashedModuleIdsPlugin will define this module list as an object, where the keys are the generated hash (from the relative file name) and the values will be the actual module code.
There is also the NamedModulesPlugin (if we're talking Webpack 3), which does the same thing but instead of a hash, the key is the actual relative path, for example:
"./node_modules/tiny-relative-date/lib/factory.js": function(e, t, n) {
In Webpack 4+, this was replaced by: https://webpack.js.org/configuration/optimization/#optimizationmoduleids
In an Ember app, when using certain dependencies like moment installed via bower, we have to also import the same in the ember-cli-build.js file:
app.import('bower_components/moment/moment.js');
My question is why is that needed, since I would assume everything inside node_modules as well as bower_components should be available for use inside the app.
Also if that is not the case, how do we identify which dependencies would require such explicit import to be able to use them ?
You don't have to, actually.
There is a package now that lets you 'just import' things: https://github.com/ef4/ember-auto-import
Some reading on the topic of importing: https://discuss.emberjs.com/t/readers-questions-how-far-are-we-from-being-able-to-just-use-any-npm-package-via-the-import-statement/14462?u=nullvoxpopuli
In in-depth answer to your question and the reasons behind why things are the way they are is posted here:
https://discuss.emberjs.com/t/readers-questions-why-does-ember-use-broccoli-and-how-is-it-different-from-webpack-rollup-parcel/15384?u=nullvoxpopuli
(A bit too long for stack overflow, also on mobile, and I wouldn't want to lose all the links and references in a copy-paste)
Hope this helps
Edit:
To answer:
I just wanted to understand "in what cases" do we need to use the import statement in our ember-cli-build (meaning we do not do import for all the dependencies we have in our package/bower.json)...But only for specific ones...I wanted to know what is the criteria or use case for doing import.
Generally, for every package, hence the appeal of the auto-import and / or packagers (where webpack may be used instead of rollup in the future).
Though, it's common for ember-addons to define their own app.import so that you don't need to configure it, like any of these shims, specifically, here is how the c3 charting library is shimmed: https://github.com/mike-north/ember-c3-shim/blob/master/index.js#L7
Importing everything 'manually' like this is a bit of a nuisance, but it is, in part, due to the fact that js packages do not have a consistent distribution format. There is umd, amd, cjs, es6, etc.
with the rollup and broccoli combo, we need to manually specify which format a file is. There are some big advantages to the rollup + broccoli approach, which can be demonstrated here
and here
Sometimes, depending on the transform, you'll need a "vendor-shim".
These are handy when a module has decided it wants to be available on the window / global object instead of available as a module export.
Link: https://simplabs.com/blog/2017/02/13/npm-libs-in-ember-cli.html
(self represents window/global)
however, webpack has already done the work of figuring out how to detect what format a js file is in, and abstracts all of that away from you. webpack is what ember-auto-import uses, and is what allows you to simply
import { stuff} from 'package-name';. The downside to webpack is that you can't pipeline your transforms (which most people may not need, but it can be handy if you're doing Typescript -> Babel -> es5).
Actually: (almost) everything!
Ember does, by default, not add anything to your app except ember addons. There are however some addons that dynamically add stuff to your app like ember-browserify or ember-auto-import.
Also just because you do app.import this does not mean you can use the code with import ... from 'my-package'. The one thing app.import does is it adds the specified file to your vendor.js file. Noting else.
How you use this dependency depends completely on the provided JS file! Ember uses loader.js, an AMD module loader. So if the JS file you app.imported uses AMD (or UMD) this will work and you can import Foo from 'my-package'. (Because this is actually transpiled to AMD imports)
If the provided JS file provides a global you can just use the global.
However there is also the concept of vendor-shims.. Thats basically just a tiny AMD module you can write to export the global as AMD module.
However there are a lot of ember addons that add stuff to your app. For example things like ember-cli-moment-shim just exist to automagically add a dependency to your project. However how it's done completely depends on the addon.
So the rule is:
If its an ember addon read the addon docs but usually you shouldn't app.import
In every other case you manually need to use the library either by app.import or manual broccoli transforms.
The only exception is if you use an addon that tries to generically add dependencies to your project like ember-browserify or ember-auto-import
If you were to write your own open source typescript library how would you structure the typescript and the typescript definitions? From what I understand the definition files are really there for the compiler so that when your library gets consumed there is intellisense to help the consumer.
However, how do definition files work internally when developing a library? Would you put all of your types (interfaces, classes, etc) in a {module}.d.ts file and reference the definition file internally so that you don't have to write the types twice (once in the {module}.ts and once in the {module}.d.ts?
In the typescript compiler options what is the point of setting "declaration" to true? To me it doesn't seem helpful to automate the definition file creation if it won't be very helpful (i.e. comments).
If your library has multiple modules would you write a separate definitions for each module and add references between definitions then concatenate them with some automater (i.e. gulp, grunt)?
What is the recommended way to expose your library so that both typescript consumers and javascript consumers can use your library?
How would you write tests in typescript? Would you import the typescript modules in your test files?
When developing your library in typescript you do not use definitions of your own classes. They are 'self contained' and already provide all type information to transpiler/IDE. The definitions are as you have mentioned for external consumers.
The point of setting declaration to true is to get rid of tedious job of collecting type information from typescript classes and pasting it in definition files. As I have said this information is already present in typescript files and can be automatically extracted by transpiler.
Regarding the way of how to organize your definitions and expose them - I am sure there are multiple different ways, one thing for sure - you do not want to write the same class definitions manually in two places. Having said that I can give you a sample of how I expose library project and consume it in another one.
Pay attention to index.ts files there and how the root one is exposed in package.json -> typings field. There you will also find exampls of unit tests for the library via jasmine.
Hope this will give you some information of how to go process with your library development.
Like it works in C# / Java e.t.c, where you don't have to worry about the location of the file, the compiler will be responsible for correctly resolving the dependencies...
At the moment relative paths are used for JavaScript modules import something from '../../../../Something' and that long path can be resolved using configurations in webpack and/or gulp e.t.c, but it is still vulnerable to file location change. So if there is a module being used in many other files moving it is not an option, better to duplicate and use new path for other files and slowly refactor the old ones.
Is there any solution to this? Am i missing something or thinking about in the wrong way? (I tried TypeScript namespaces but they don't act like this, weren't what i expected, and i'm not that into using languages that compile to JS)
It seems the TypeScript compiler always includes lib.d.ts or lib.es6.d.ts (depending on the compiler target).
In our application we have a WebSocket class that is already defined in lib.d.ts. We're running our application under Node.js and not in a web browser, so we actually don't need all of the definitions from lib.d.ts. Instead lib.core.d.ts would be sufficient for us (and would solve the WebSocket conflict of course).
Is it possible to tell the TypeScript compiler which global type definition file to use?
Use --noLib compiler option to exclude lib.d.ts and then add reference to lib.core.d.ts in your source files.
Equivalent for tsconfig.json would be "noLib": true.
If you only need Node.js definitions, you can also use the Definitely Typed one.
Another solution might be to use lib like core-js. which has all the required polyfils for ES6. Note: you will also will need to add the core-js tsd file to your tsds.
Hope it helps.