Webpack importing all the files from the export file in production bundle - ecmascript-6

Webpack not removing unused code in production (final) bundle
Here is my scenario
file-a.js
import {otherfunction} from "./anotherFile.js"
export const sendAjaxRequest() /** common function to send a ajax Request**\
file-b.js
import {sendAjaxRequest} from "./file-a.js"
consuming the imported method
Final Bundle Contains all the method of file-a.js
set sideEffect false in package.json
configured babel to stop transpile module (
['#babel/preset-env',{modules: false}])
Final Bundle :- file-b.js + file-a.js + file-a *imports files.js
What am missing ?

Related

WebStorm generates bad import paths

My project has this structure:
root/
---tsconfig.json
---app/
------main.ts
---lib/
------public_api.ts
------files/
---------index.ts
---------file2.ts
---------file3.ts
The index.ts file in lib/ is a barrel file that exports all files in ./files:
# index.ts
export * from './file2';
export * from './file3';
The public_api.ts file exports whatever the barrel exposes
# public_api.ts
export * from './files'
Finally, tsconfig has a path alias for all files under lib/ like this:
"paths": {
"lib": ["lib/public_api.ts"]
}
With this setup, from within my app's main.ts I can import my library classes without using the full path:
# main.ts
import { File2Class } from 'lib';
That works well, and my IDE (PhpStorm / Webstorm) will know to automatically generate imports with the path alias when I'm in main.ts.
The problem is that sometimes when I am within a lib/files/*.ts file and I use a class from a sibling file, the IDE will use the same alias, so from within file3.ts It would auto-generate one of these imports:
# file3.ts
import { File2Class } from 'lib';
or
import { File2Class } from './';
This causes a hard to debug compilation error though. The correct import from a sibling file would be:
# file3.ts
import { File2Class } from './file2';
So my question is: is it possible to instruct Webstorm/PhpStorm to never use a parent path and to never import from the barrel in the current or parent directory?

Angular 6 with lowdb - not getting it to work

I'm trying to create an Electron app with Angular 6 that uses lowdb as a local database.
It's all very new to me and it's trial and error, but I don't seem to be able to figure out how to overcome the following error:
I've installed lowdb in my application by using the commands
npm install --save lowdb (edit: forgot to mention I did this already)
and
npm install --save #types/lowdb
I've created a service to communicate with this "local database".
import { Injectable } from '#angular/core';
import lowdb from 'lowdb';
import { default as FileAsync } from 'lowdb/adapters/FileAsync';
import { CurrentUserModel } from '../models/current-user';
#Injectable({
providedIn: 'root'
})
export class LowdbService {
private db: lowdb.LowdbAsync;
constructor() {
this.initDatabase();
}
set( field: string, value: any ) {
this.db.set( field, value ).write();
}
private async initDatabase() {
const adapter = new FileAsync( 'db.json' );
this.db = await lowdb( adapter );
this.db.defaults( { user: CurrentUserModel } );
}
}
But when I include the service in the constructor of a component I get errors.
ERROR in ./src/app/services/lowdb.service.ts
Module not found: Error: Can't resolve 'lowdb' in '/Users/paul/Projects/application-name/src/app/services'
ERROR in ./src/app/services/lowdb.service.ts
Module not found: Error: Can't resolve 'lowdb/adapters/FileAsync' in '/Users/paul/Projects/application-name/src/app/services'
ℹ 「wdm」: Failed to compile.
ERROR in src/app/services/lowdb.service.ts(2,12): error TS1192: Module '"/Users/paul/Projects/application-name/node_modules/#types/lowdb/index"' has no default export.
src/app/services/lowdb.service.ts(3,14): error TS2305: Module '"/Users/paul/Projects/application-name/node_modules/#types/lowdb/adapters/FileAsync"' has no exported member 'default'.
As far as I can see I'm doing the same as mentioned in this Github comment and this Stackoverflow comment. I can't find any more documentation though.
Can somebody help me out?
Update
Using import * as lowdb from 'lowdb' seemed to solve my initial errors. But it resulted in a few other errors. See below.
ERROR in ./node_modules/graceful-fs/polyfills.js
Module not found: Error: Can't resolve 'constants' in '/Users/paul/Projects/project-name/node_modules/graceful-fs'
ERROR in ./node_modules/graceful-fs/graceful-fs.js
Module not found: Error: Can't resolve 'fs' in '/Users/paul/Projects/project-name/node_modules/graceful-fs'
ERROR in ./node_modules/graceful-fs/fs.js
Module not found: Error: Can't resolve 'fs' in '/Users/paul/Projects/project-name/node_modules/graceful-fs'
ERROR in ./node_modules/graceful-fs/legacy-streams.js
Module not found: Error: Can't resolve 'stream' in '/Users/paul/Projects/project-name/node_modules/graceful-fs'
First of all, if you installed just #types/lowdb, that is only typings for that library, you need to install the library itself via:
npm install --save lowdb
Then, looks like there is no default export so import lowdb from 'lowdb'; also won't work. Try is like this:
import { LowdbAsync } from 'lowdb';
import * as lowdb from 'lowdb';
import * as FileAsync from 'lowdb/adapters/FileAsync';
private db: LowdbAsync<any>; // TODO provide correct schema instead of any
private async initDatabase() {
const adapter = new FileAsync('db.json');
this.db = await lowdb(adapter);
this.db.defaults({ user: any });
}
Or you can try removing those typings (as they might be outdated) and do what their docs says:
https://github.com/typicode/lowdb/tree/master/examples#browser
import low from 'lowdb'
import LocalStorage from 'lowdb/adapters/LocalStorage'
(but when you take a look at #types/lowdb, there is no such default export so again, the typings might be outdated)
As for your other issue, take a look here:
https://github.com/typicode/lowdb/issues/206#issuecomment-324884867
typicode commented on 25 Aug 2017
#DickyKwok I think it's impossible. Can you answer this, #typicode?
I confirm, to save to disk using FileSync or FileAsync adapters you need to have access to Node fs API.
Looks like you should use LocalStorage adapter instead.
Another similar issue here: How can I use node "fs" in electron within angular 5
You could also try the solution proposed in one of answers there:
https://github.com/ThorstenHans/ngx-electron
constructor(private _electronService: ElectronService) {
this.fs = this._electronService.remote.require('fs');
}
Looks like your lowdb is missing in node_modules.
try
npm install lowdb

How to import external JavaScript into Polymer 3.0

Let's say I have a traditional javascript library such as google-charts and I wanted to incorporate that into my Polymer 3.0 project. How would I actually do the import?
This is how I would traditionally do it: https://developers.google.com/chart/interactive/docs/quick_start
ES Modules on NPM
Normally, one would prefer an ES module version of such a library if available (e.g., on NPM), since ES modules allow tree shaking (by Polymer CLI in this case) to reduce the size of the production build output.
Modules are loaded in JavaScript with the import keyword. If available on NPM, the library could be installed in your Polymer project with the npm-install command. For instance, you'd install google-charts like this:
npm install --save google-charts
Then, import that package in your element code:
import { GoogleCharts } from 'google-charts';
Example:
import { PolymerElement } from '#polymer/polymer';
import { GoogleCharts } from 'google-charts';
class MyElement extends PolymerElement {
// ...
ready() {
super.ready();
GoogleCharts.load(/* ... */);
}
}
demo
Non-ES Modules (not on NPM)
On the other hand if ESM is unavailable, the script is likely an AMD/UMD module, which adds symbols to the global scope. In that case, you'd still import the file, and access the global as you normally would had you used the <script> tag.
If the script is not on NPM, you'd have to copy the file locally into your project (and include the library file in your release), and then import the file by path. For example, if you copied the library to <root>/src/libs/google-charts.js, the element code at <root>/src/components/Chart.html would import it like this:
import '../libs/google-charts'
Example:
import { PolymerElement } from '#polymer/polymer';
import '../libs/google-charts' // adds GoogleCharts to global
class MyElement extends PolymerElement {
// ...
ready() {
super.ready();
GoogleCharts.load(/* ... */);
}
}

How can I install separate mixpanel projects for development and production in angular5/angularitics

I have already configured mixpanel in my angular 5 app. Now I want to separate mixpanel project for production and development. I have already added mixpanel script snippet in index.html in head section containing token of production project. Now I need to add another token and select one based upon selected environment, but environment variable is not accessible in index.html. I don't want to have two separate index.html in my project. In another way as suggested here (How to integrate mixpanel with angular2).I set token from main.ts, but it is unable to access environment variable.Is there any way to set token in index.html based upon selected environment?
I am getting following error:
ERROR in /home/Project/src/main.ts (9,27): Property 'mixpanel' does not exist on type '{ production: boolean; }'.
exported api key from environment.ts:
export const mixpanel= {
apikey: 'MY_PROJECT_TOKEN_HERE'
}
main.ts
import { enableProdMode } from '#angular/core';
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
declare const mixpanel: any;
enableProdMode();
mixpanel.init(environment.mixpanel.apikey);
platformBrowserDynamic().bootstrapModule(AppModule);

How to troubleshoot es6 module dependencies?

I am developing a React & Reflux app, which is bundled by webpack with babel-loader (v6), and I am experiencing es6 modules dependencies issues
For example, I have a component that use the reflux .connect() mixin :
import MyStore from '../stores/my-store';
const Component = React.createClass({
mixins: [Reflux.connect(MyStore)]
});
When I import all modules individually in each file like this, everything's fine.
I then tried to improve my code by using deconstructed import statements :
...in a component :
//import One from '../js/one';
//import Two from '../js/two';
//import Three from '../js/three';
import { One, Two, Three } from '../js'; // Instead
...and in js/index.js :
import One from './one';
import Two from './two';
import Three from './three';
export { One, Two, Three };
App source code files are more concise using the above technique, because I can import all components in one import line.
But when I use this, some dependencies end up beeing undefined when I use them
If I use the same updated example...
//import MyStore from '../stores/my-store';
import { MyStore } from '../stores'; // Instead
const Component = React.createClass({
mixins: [Reflux.connect(MyStore)]
});
...MyStore parameter ends up undefined in Reflux.connect method.
I tried to troubleshoot in the debugger, but I'm not really aware of what's going on with the __webpack_require__(xxx) statements in the generated bundle. There must be a circular dependency that babel-loader or webpack require could not figure out when there are the index.js files re-exporting individual modules.
Do you know any tool that can help me figure this out? I tried madge but it does not work with es6 modules, and I could not find anything that would tell me where anything is wrong
In order to get extended info about build, run:
webpack --profile --display-modules --display-reasons
It will give you bunch of information for optimisation/profiling.
import statement is used to import functions, objects or primitives that have been exported from an external module.
As per MDN doc, you can import the Modules not the directory.
import name from "module-name";
import * as name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import defaultMember, { member [ , [...] ] } from "module-name";
import defaultMember, * as alias from "module-name";
import defaultMember from "module-name";
import "module-name";
Reference URL:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
http://es6-features.org/#ValueExportImport
https://github.com/lukehoban/es6features#modules
http://www.2ality.com/2014/09/es6-modules-final.html
As a workaround keep one file as base.js and include all your 3 files.