Can't import bundled file - javascript

I'm doing this in my application
System.import('lib/bootstrap.js').then(m => {
this.socket = m.io("http://localhost:3000");
})
This is bootstrap.js
import io from 'socket.io-client';
export { io };
I created a bundle via jspm bundle lib/bootstrap.js outfile.js.
When I try to System.import('outfile.js') the resolved Promise m is only an empty Object.
What am I doing wrong here?
System.import('outfile.js').then(m => {
this.socket = m.io("http://localhost:3000");
})

You don't want to import the bundled file. What you need to do is inject the bundle configuration to your config.js file. For example adding jspm bundle lib/bootstrap bootstrap-bundle.js --inject will add
"bundles": {
"bootstrap-bundle": [
"socket.io-client.js",
"lib/bootstrap.js"
]
}
to your config.js file. Then you just need to import your file as usual:
System.import('lib/bootstrap.js').then(m => {
this.socket = m.io("http://localhost:3000");
})
See the documentation here.

Related

Modify build path of assets in Vite/Rollup?

Let's say I have this folder structure:
parent
|-parent.html
|-parent.js
|-child
|--child.html
|--child.js
I want them to output in the same structure in my dist folder.
By default this is what gets output:
dist/assets/parent.js
dist/assets/child.js
I want them to output like this:
dist/parent/parent.js
dist/parent/child/child.js
I tried changing the assetFileNames option of Rollup but it didn't do anything.
The output filenames are configured in Rollup with build.rollupOptions. Set output.entryFileNames to configure the location of the entry .js files to match their original directory structure:
// vite.config.js
import { fileURLToPath } from 'url';
import { defineConfig } from 'vite';
import path from 'path';
const rootDir = fileURLToPath(new URL('.', import.meta.url));
export default defineConfig({
build: {
rollupOptions: {
input: {
parent: './parent/parent.html',
child: './parent/child/child.html',
},
output: {
entryFileNames: (assetInfo) => {
// assetInfo.facadeModuleId contains the file's full path
if (assetInfo.facadeModuleId) {
const assetPath = path.dirname(assetInfo.facadeModuleId).replace(rootDir, '');
return assetPath + '/[name]-[hash].js';
} else {
return 'assets/js/[name]-[hash].js';
}
},
},
},
},
});
demo
Notes
Assets (such as .css files) and shared modules (vendor .js chunks) cannot be redirected with the solution above because the asset info from the related hooks do not provide the file's full path.
In a vanilla Rollup project, output.preserveModules=true would've accomplished the original goal, but that option conflicts with Vite's own settings for Rollup.

Webpack: ModuleNotFoundError for an unimported module

The problem
My project consists of a yarn monorepo in which, among various packages, there is a NextJS app and a configuration package (which is also shared with the server and a react-native application). In the configuration module what I do is to export the production keys if the environment is production, while if the project is under development, the development ones.
import { merge } from "lodash";
import { IConfig, RecursivePartial } from "./interfaces";
import { defaultKeys } from "./default.keys";
import { existsSync } from "fs";
const secretKeys: RecursivePartial<IConfig> = (function (env) {
switch (env) {
case "production":
return require("./production.keys").productionKeys;
default:
try {
if (!existsSync("./development.keys")) {
return require("./production.keys").productionKeys;
} else {
return require("./development.keys").developmentKeys;
}
} catch (e) {
}
}
})(process.env.NODE_ENV);
export const keys = merge(defaultKeys, secretKeys) as IConfig;
Of course, the development configuration file is included in the .gitignore file and therefore does not exist during production.
This has always worked perfectly (with the server and the mobile app), and indeed, there was never the need to check with the fs module if the development.keys file exists (check which I added later).
However, I recently added a NextJs application to the project. I encountered no problems during development, however when I tried to deploy the app on Heroku I encountered this error:
ModuleNotFoundError: Module not found: Error: Can't resolve './development.keys' in '/tmp/build_43d652bc/packages/config/dist/keys'
What I did
Initially, I thought it was a problem with the environment variables and that in production the development file was wrongly required.
However, I later realized that this was not the problem. And indeed, even placing the import of the configuration file for development in any place of the code, even following a return, the error continues to occur.
import { merge } from "lodash";
import { IConfig, RecursivePartial } from "./interfaces";
import { defaultKeys } from "./default.keys";
import { existsSync } from "fs";
const secretKeys: RecursivePartial<IConfig> = (function (env) {
switch (env) {
case "production":
return require("./production.keys").productionKeys;
default:
try {
if (!existsSync("./development.keys")) {
return require("./production.keys").productionKeys; // <-------
} else {
return require("./production.keys").productionKeys; // <-------
}
require("./development.keys").developmentKeys; // <------- This line should not be executed
} catch (e) {
return require("./production.keys").productionKeys;
}
}
})(process.env.NODE_ENV);
export const keys = merge(defaultKeys, secretKeys) as IConfig;
It is as if during the build, nextjs (or probably webpack) controls all the imports, without following the "flow" of the code.
I hope someone shows me where I am wrong because at the moment I am stuck. Thank you!
Update
Thanks to the ideas of this discussion I changed my file which now looks like this:
const getConfigPath = (env?: string): string => {
console.log(env);
if (env === "production") return "production.keys";
else return "development.keys";
};
const secretKeys: RecursivePartial<IConfig> = require("./" +
getConfigPath(process.env.NODE_ENV)).keys;
export const keys = merge(defaultKeys, secretKeys) as IConfig;
However, now I'm running into another webpack error:
Module parse failed: Unexpected token (2:7)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| import { IConfig, RecursivePartial } from "../interfaces";
> export declare const keys: RecursivePartial<IConfig>;
It is as if webpack does not recognize declaration files generated by typescript. However, the error is new and I have never encountered it. I believe it's due to the behavior of webpack pointed out in the linked discussion.
I trust in some help, since I know little about webpack
Edit
This is my next.config.js:
const path = require("path");
module.exports = {
distDir: '../../.next',
sassOptions: {
includePaths: [path.join(__dirname, 'styles')],
prependData: `#import "variables.module.scss";`
},
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.fallback.fs = false;
}
return config;
},
};
Basically they are the defult configurations. The only thing I have changed is the path for the build, I have made a sass file globle and I have momentarily added a piece of code to allow the use of the fs module, which however as you can see above I do not use it more. So I could take this configuration out.
You need the loader for typescript configured in your next.config.js
npm install || yarn add awesome-typescript-loader
module.exports = {
distDir: '../../.next',
sassOptions: {
includePaths: [path.join(__dirname, 'styles')],
prependData: `#import "variables.module.scss";`
},
webpack: (config, options) => {
const { dir, defaultLoaders, isServer } = options;
if (!isServer) {
config.resolve.fallback.fs = false;
}
config.pageExtensions.push(".ts", ".tsx");
config.resolve.extensions.push(".ts", ".tsx");
config.module.rules.push({
test: /\.tsx?$/,
include: [dir],
exclude: /node_modules/,
use: [
defaultLoaders.babel,
{
loader: "awesome-typescript-loader",,
},
],
});
return config;
}
}

Using jest with files with glob imports

I utilize webpack with webpack-import-glob-loader to import files using glob pattern. So in one of my files (src/store/resources/module.ts) I have a line:
import '../../modules/resources/providers/**/*.resource.ts';
When I run a test with ts-jest it fails and reports the following message:
Cannot find module '../../modules/resources/providers/**/*.resource.ts' from 'src/store/resources/module.ts`
I assume it complains because it can't recognize this import syntax.
How to make jest work for project with glob imports?
I solved this by manually handling the globs inside of a jest preprocessor. Since you need to control processing of the files to handle globs in this approach, you have to manually initialize your processor.
// config.js
module.exports = {
transform: {
'.': `./path/to/your/processor.js`
// processor.js
const path = require(`path`);
const glob = require(`glob`).sync;
const yourProcessor = // require your processor code - ts-jest, babel-jest, esbuild-jest, etc
module.exports = {
process(src, filename, config, opts) {
const dir = path.dirname(filename);
src = processGlob(src, dir);
return yourProcessor(src, filename, config, opts);
},
};
function processGlob(src, dir) {
// This will match things like
// import './**/*';
// import '../../modules/resources/providers/**/*.resource.ts';
// Takes inspiration from https://github.com/excid3/esbuild-rails/blob/main/src/index.js
return src.replace(/^import\s'(.*\*.*)';$/m, (_match, pathCapture) => {
const matcher = /.+\..+/; // Handles '.' results
const files = glob(pathCapture, {
cwd: dir,
})
.sort()
.filter((path) => matcher.test(path));
return `${files.map((module, index) => `import * as module${index} from '${module}'`).join(`;`)}`;
});
}
In this approach you can only glob once per file (because it uses the .map indexes to add numbers to each import module name). You could keep track of a global count variable instead, if you wanted to have several glob imports in one file.

How to import .json config to environment.ts and consume api using Angular?

I want to import a Json file which is in assets folder where I have below urls:
config.json:
{
"url1": "https://jsonplaceholder.typicode.com/posts",
"url2" : "https://reqres.in/api/users",
"url3":"https://fakerestapi.azurewebsites.net/api/Authors"
}
So instead of hard coding the URL, I want to import from Json file, but I am not sure how to do that exactly.
Any suggestions or scenarios would be appreciated, below are my issues:
1. How to import Json file to environment.ts and from there I will have a service which consumes the api
2. If I import the file, it needs to be the same for prod and loc dev also
what I want :
I have a config file where it contains some URL's in .json file stored in asset folder now instead of loading environments.prod or .ts, I want to load my Json file config and basing on that I want to run my application
what I did:
Below is my Json file which I placed in asset folder
{
"baseUrl": "https://jsonplaceholder.typicode.com/",
"baseUrl2": "https://reqres.in/api/users"
}
ConfigServiceService.ts for storing config file
public _config: Object;
constructor(public http:Http) { }
getData(){
debugger;
return this.http.get("./assets/config.json").pipe(map(res => res.json()));
}
After this, I create a ServiceProviderService.ts for calling the service file
configData:any;
constructor(public http:Http,public config:ConfigServiceService) {
}
jsonData(){
debugger;
return this.configData;
}
ngOnInit(){
debugger;
this.config.getData().subscribe(res =>{
console.log(res);
this.configData = res;
});
}
app.component.ts
title = 'sample';
constructor(public serv :ServiceProviderService){
this.serv.jsonData();
}
I am not able to get the Json data and if I am putting the logic which is there is ngOnInit in ServiceProviderService.ts file if I put it in constructor then I am getting undefined.
Note : here if there are more than once url then each url is distributed to various seperate service file suppose base1 url for 1 service file ans base2 url for another file how can I achieve that
https://stackblitz.com/edit/read-local-json-file-5zashx
in app.component.ts im getting undefined
Since you have static strings in a JSON file, which is already saved in /assets folder and it's not on the server, you don't need to use http.get.
We use http protocol to get data from JSON files from the server/backend only, not from the client side folders.
You just need to import the JSON file wherever you need (even in environment.ts), as you would do with DTOs.
Use Typescript's ES6 import statement combined with export in the JSON file.
assets/config.ts
export const URLS = Object({
"url1": "https://jsonplaceholder.typicode.com/posts",
"url2" : "https://reqres.in/api/users",
"url3":"https://fakerestapi.azurewebsites.net/api/Authors"
})
Then anywhere (components, directives, services, classes, interfaces, etc ...)
import { URLS } from 'assets/config.ts';
....
this.url1 = URLS.url1;
//or
let url1 = URL.url1;
Now this.url1 can be used in any api call inside http.get, for example:
this.http.get(`${this.url1}`, { headers: this.getHeaders(token) });
or
this.http.get(`${url1}`, { headers: this.getHeaders(token) }) // where url1 could be a variable or method parameter, etc...
That's it
You can create a service to read Json file using HttpClient
export class SettingService {
constructor(private http: HttpClient) {
}
public getJSON(file): Observable<any> {
return this.http.get("./assets/configs/" + file + ".json");
}
public getSetting(){
// use setting here
}
}
You should save 3 url to session storage or localstorage instead of enviroment.ts incase you refresh page
Refer Angular: Is it possible to read a json file after building
You can use required 🤔 to read a json file from assets
/assets/urls.json 📄
{
"urls": {
"dev": "dev.com",
"prod": "prod.com"
}
}
env.ts
const { urls } = require("../assets/urls.json");
export const environment: IEnv = {
production: false,
baseUrl: urls.dev
};
env.prod.ts
const { urls } = require("../assets/urls.json");
export const environment: IEnv = {
production: true,
baseUrl: urls.prod
};
🚨 you need to install npm i #types/node and update tsconfig.app.json like this
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"types": ["node"]
},
"exclude": ["test.ts", "**/*.spec.ts"]
}
You can create constants for all these urls in environment file. I do not see a scenario in your case to put it in a separate json file. For prod, you can use the same environment file by changing default configurations property in angular.json
import { environment } from '../../../environments/environment';
domain :string = environment.domain;
if(!!environment) {
if(environment.qa) {
"url1": "https://jsonplaceholder.typicode.com/posts",
}
if(environment.dev) {
"url2" : "https://reqres.in/api/users",
}
}
you can import the baseUrl property in the asset folder to your service file and execute as I mentioned above.
https://alligator.io/angular/environment-variables/
Please find the url for detailed explanation of environment variables in angular
So, I would create a node script called populatedDynamicUrls.js that can read those values IN from the json file, and write those values OUT to the corresponding environment.ts file for that specific environment. THEN your angular build command would look like this: node populateDynamicUrls.js && ng run build, and your angular serve command would look like this: node populateDynamicUrls.js && ng run serve
If you want to import json file
Add config.json to the assets directory.
Edit typings.d.ts file:
declare module "*.json" {
const value: any;
export default value;
}
Add path of typings.d.ts to "typeRoots" in tsconfig.json, for example:
"typeRoots": [
"node_modules/#types", "./src/typings.d.ts"
],
Import config.json in environment file:
import * as config from '../assets/config.json';
export const environment = {
baseUrl: config.default.url1
production: true
};
That's all, good luck!
I'm not sure if this is the best solution, but here's what I did (by cut'n'pasting what was already in the default Angular project). I had the same goal: I wanted an "API URL" to be available, depending on which environment (Debug or Production) we were using.
First, I added an extra config setting to the two existing .ts files:
src\environments\environment.prod.ts
src\environments\environment.ts
..so now, each of the files looked something like this:
export const environment = {
production: false,
apiUrl: "http://localhost:53104"
};
The main.ts file already has code to read in the environment object, and it uses the environment.production value, so I just added a bit of code to this file to do the same with the environment.apiUrl value:
export function getAPIUrl() {
console.log("API URL: " + environment.apiUrl);
return environment.apiUrl;
}
const providers = [
{ provide: 'BASE_URL', useFactory: getBaseUrl, deps: [] },
{ provide: 'API_URL', useFactory: getAPIUrl, deps: [] }
];
. . .
platformBrowserDynamic(providers).bootstrapModule(AppModule)
.catch(err => console.log(err));
With this in place, I can access this new "API_URL" value in my components.
For example:
export class FetchDataComponent {
public forecasts: WeatherForecast[];
constructor(http: HttpClient, #Inject('BASE_URL') baseUrl: string, #Inject('API_URL') APIUrl: string) {
http.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => {
this.forecasts = result;
}, error => console.error(error));
console.log("FetchDataComponent, URL: " + APIUrl);
}
}
When I open this page, I can see my URL shown in the Output window.
FetchDataComponent, URL: http://localhost:53104
Is this solution okay ? It seems a lot simpler (with almost no code) than the other solutions.
Actually, an even simpler solution is to not use a "API_URL" provider, and just stick this in your components:
import { environment } from '../../environments/environment';
..then just access the value using:
console.log("FetchData, URL: " + environment.apiUrl);
Job done !

Import Resource Bundle to vue project

I want to add package ResourceBundle to my vue project.So i installed it:
npm install resource-bundle
These are export parts in index.js resourcebundle package:
export function* loader (locale, dir, baseName) {
console.log('in loader')//Does not print
...
return new ResourceBundle(require(file))
};
function ResourceBundle (resource) {
this.resource = resource
}
ResourceBundle.prototype.get = function (key) {
...
return util.format.apply(util, params);
};
export const ResourceBundlee = ResourceBundle
Then import it in main.js and use 'loader':
import * as ResourceBundle from 'resource-bundle'
console.log(ResourceBundle)
//console:
// ResourceBundlee:Æ’ s(t)
// loader:Æ’ r(t,e,n)
console.log(ResourceBundle.loader('en_US',
__dirname+'/resources',message').get)
//console:
//undefined
I do not know javascript.Would you please explain what is happening and why does not print 'in loader' and how should i import loader in correct way? thanks
npm install ResourceBundle should be npm install --save resource-bundle. Try re-installing with the correct package name and the save flag.
After that, check the package.json file in your project root directory for resource-bundle listed in the "dependencies" section.
"dependencies": {
...
"resource-bundle": "^0.1.2",
...
}
Changed your import statement to:
import loader from 'resource-bundle'
And call the loader function:
let message = loader('en_US', __dirname+'/resources',message')
console.log(message.get('some-key'))

Categories

Resources