I'm working on a nodeJs/Typescript app and I would like to be able to launch it from the dist/ folder.
The structure of each src and dist folders is something like that :
server/
|---dist/
| |---server/
| |---src/
| |---index.js
| |---utils/
| |---connection.js
|---src/
| |---index.ts
| |---utils/
| |---connection.ts
|
|---package.json
|---tsconfig.json
This dist folder is the generated code, with this path being configured using outDir inside of my tsconfig.json file.
I have also configured the main property in my package.json to be dist/server/src/index.js and the type property to be module
In this project, I am using Typescript 4.0.5
I have specified paths property in my tsconfig.json to be "utils/*" : ["src/utils/*"], the baseUrl property to be './' and the property moduleResolution strategy to be node
Now this is my issue. I would like to be able to import my modules the same way i do in my source code, but this time directly from the dist folder, like this :
import createConnection from 'utils/connexion';
However, when i hover the import declaration in VScode, it does not seems to resolve the module and i get an error Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'utils' imported from /home/maxime/Dev/JeuxDuPlacard/packages/server/dist/server/src/index.js
When i do the same operation from my Typescript files, it works as expected.
The paths of the files in the dist folder is the same in the Server folder. If the problem comes form the module resolution, Is there a way to persist the paths aliases in the dist folder (without installing a third party library) ?
{
"compilerOptions": {
"esModuleInterop": true,
"target": "es2020",
"moduleResolution": "node",
"sourceMap": true,
"baseUrl": "./",
"outDir": "dist",
"strict": true,
"lib": ["ES2017", "ES2020"],
"types": [
"node"
],
"allowSyntheticDefaultImports": true,
"noImplicitAny": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"resolveJsonModule": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"incremental": true,
"skipLibCheck": true,
"strictPropertyInitialization": false,
"paths": {
"utils/*": ["src/utils/*"]
}
}
}
Thanks
That's right, because you CAN'T import files from outside your workdir. What you could do, is you could link a local module and access it as you would any other npm package.
npm link (in package dir)
npm link [<#scope>/]<pkg>[#<version>]
alias: npm ln
https://docs.npmjs.com/cli/v6/commands/npm-link
Related
I want tsc to compile my project as:
built/
- package.json
- app.js
- etc.
not:
built/
- test/lambda/first/src/
- app.js
- package.json
my tsconfig looks like this currently:
{
"compilerOptions": {
"module": "CommonJS",
"target": "ES2017",
"noImplicitAny": true,
"preserveConstEnums": true,
"declaration":true,
"baseUrl": "./",
"outDir": "./built",
"sourceMap": true,
"paths": {
"#utils/*": ["../../../common/layers/test2/*"]
},
"esModuleInterop": true
},
"include": ["./**/*"],
"exclude": ["node_modules"]
}
And what i want to do is tell tsc to dont compile the folder "common" inside my built folder and also dont make a file structure like this? Is it possible with only tsconfig settings? I know how to do it with linux commands, but the point would be that tsc should handle it.
(I only want to use paths for developing, i dont actually want them in my built folder because it will access those files in the cloud)
So we have a ReactTs project and we implemented shortcuts to things like our utils folder, So instead of calling the relative path everytime we use it in a module we just call #utils. We did this by adding path in our tsconfig.json.
This feature looks so handy and clean we decided to do the same on our Nodejs Typescript application. But when we compile the project and run the compliled js project it returns an error that seems #utils is not found. is there a way over this? How can we tell to compile the #utils to the declared relative path?
tsconfig file:
{
"compilerOptions": {
"module": "commonjs",
"outDir": "./build",
"strict": true,
"baseUrl": "./",
"paths": {
"#interface": [
"interface/index.ts"
],
"#utils":[
"src/utils/index.ts"
]
},
"types": [
"node_modules/#types"
],
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
Project directory:
So to solve this I implemented this npm: https://www.npmjs.com/package/module-alias.
I have a TypeScript React project organized as follows:
tsconfig.json
package.json
yarn.lock
lerna.json
node_modules/
packages/
ui-library/
package.json
tsconfig.json
typings.d.ts
src/
fonts/
myfont.ttf
components/
GlobalStyle.tsx
lib/ <-- `tsc` builds to here
web-app/
package.json
src/
components/
The web-app imports the ui-library as a commonjs module in its package.json. This is managed through Yarn Workspaces, hence node_modules being at the root instead of each folder. At one point, the web-app imports GlobalStyle from the ui-lib, which is where the issue occurs.
Error: Cannot find module '../fonts/myfont.ttf'
Require stack:
- /Users/me/sources/myproject/packages/ui-library/lib/styles/GlobalStyle.js...
Here is the original import statement from ui-library/src/GlobalStyle.tsx that causes the issue:
import myFont from "../fonts/myfont.ttf";
const GlobalStyle = () => (
<style global jsx>{`
#font-face {
font-family: "My font family";
src: url(${myFont}) format("truetype");
}
...</style>);
The issue is the require statement in the emitted GlobalStyle.js code, built when I run tsc in the ui-lib folder:
const MYFONT_ttf_1 = __importDefault(require("./myfont.ttf"));
I googled this issue online, and I found you had to add typings for compiling .ttf and other abnormal imports. So I created a typings.d.ts file with this declaration:
declare module "*.ttf" {
const value: string;
export default value;
}
And I included it on ui-library/tsconfig.json as follows:
{
"extends": "../../tsconfig.json",
"exclude": ["lib"],
"include": ["src"],
"files": ["./typings.d.ts"],
"compilerOptions": {
"baseUrl": "src",
"outDir": "lib",
"declaration": true,
"declarationMap": true,
"noEmit": false
}
}
The tsconfig above extends the root tsconfig:
{
"files": ["./typings.d.ts"],
"compilerOptions": {
"module": "commonjs",
"target": "es2019",
"lib": ["dom", "es2019"],
"strict": true,
"jsx": "react",
"moduleResolution": "node",
"isolatedModules": true,
"esModuleInterop": true,
"noUnusedLocals": false,
"forceConsistentCasingInFileNames": true,
"strictNullChecks": true,
"sourceMap": true,
"noEmit": true,
"declaration": false
},
"exclude": ["node_modules"]
}
We are using TypeScript 3.8. Let me know if there is any additional info to provide. My hunch is that I am either using the wrong module/target, or fundamentally misunderstanding some aspect of this.
More Details
I should note the reason we are using CommonJS modules is because ts-node can only work with that. We pull in ts-node when we are doing our gatsby build, following the gist here in gatsby-config.js:
require("ts-node").register();
// Use a TypeScript version of gatsby-config.js.
module.exports = require("./gatsby-config.ts");
Maybe it's an impossible problem to solve, to get fonts imported through ts-node which is a server side environment? Confused on what the right approach is to export a module with fonts. Willing to get rid of ts-node, and leave the Gatsby config files as js.. but mostly just want to be able to import my fonts.
I solved this by just copying the fonts as part of build steps. Basically, fonts have their own pipeline. There may be better ways, but this works well enough.
The package I'm building (https://github.com/plastikfan/xiberia/tree/develop) is a type only package (I'm not using DefinitelyTyped and this question is not about DT).
The package essentially is just a single file (index.ts) which contains various exported types such as:
export interface IYargsFailHandler {
(msg: string, err: Error, inst: yargs.Argv, command: any): yargs.Argv;
}
The problem is, when I use this in a client app, most of the types are missing and the only type that appears by intellisense is:
export const CoercivePrimitiveStrArray = ['boolean', 'number', 'symbol'];
All the other types are missing.
When I look at the corresponding index.js file, all it contains is:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CoercivePrimitiveStrArray = ['boolean', 'number', 'symbol'];
// -----------------------------------------------------------------------------
//# sourceMappingURL=index.js.map
The generated index.d.ts looks correct and contains all the types, (well there is one very weird definition that I can't account for at the end of the file):
export {};
My typescript config file is:
{
"compilerOptions": {
"allowJs": true,
"alwaysStrict": true,
"esModuleInterop": true,
"module": "commonjs",
"moduleResolution": "Node",
"noImplicitAny": true,
"sourceMap": true,
"strictNullChecks": true,
"target": "es5",
"declaration": true,
"declarationDir": "./dist",
"outDir": "./dist",
"diagnostics": true,
"lib": [
"es5",
"es2015",
"es6",
"dom"
],
"types": [
"node", "yargs"
],
},
"include": [
"./index.ts"
],
"exclude": [
"node_modules",
"dist"
]
}
So why are most of the types missing and how do I correct it, thanks.
EDIT: OOPS, I just made a really silly mistake. The types should not be in the resultant .js file. The only valid js is indeed the CoercivePrimitiveStrArrayCoercivePrimitiveStrArray which is being exported.
But that doesnt explain why the types that are being exported are not shown by intellisense on the clienbt side.
So on the client, this is what I have:
in a client file:
import * as xiberia from 'xiberia';
When I type, "xiberia.", I would expect to see all the types being exported, but I don't see any.
I read up on the triple slash directive and it appears they are not appropriate for this situation.
So what other config setting do i need for te intellisense to work as expected?
I fixed this problem by simplifying the package as much as possible. Previously, I was building artefacts into the 'dist' folder, a pattern which is widely used. I have removed this (this is a simple single file package, so using a dist folder is overkill) and simply build out the resultant index.d.ts, index.js and the .map files into the root directory. This also required explicity specifiying these files in the 'files' property in package.json (this ensures that these files are included in the resultant package tarball built when performing npm pack via the publish mechanism).
I don't understand why now intellisense is working as a result of these actions; perhaps somebody who knows better can comment.
I had a problem this morning that was driving me crazy. I'll explain the issue and then I'll provide my answer below (so that others who come across this can get to a solution sooner).
It is very easy to duplicate the issue by just issuing these commands:
tsd query react --action install
mkdir src
echo "import React = require('react');" > src/foo.ts
I also included the following tsconfig.json file in src:
{
"version": "1.6.2",
"compilerOptions": {
"outDir": "./tsdir",
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"isolatedModules": false,
"jsx": "react",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"declaration": true,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"preserveConstEnums": true,
"suppressImplicitAnyIndexErrors": true
},
"files": [
"foo.ts"
]
}
If I try to compile this by simply running the tsc (version 1.6.2) command inside src, I get:
foo.ts(1,24): error TS2307: Cannot find module 'react'.
What I find baffling here is that I've installed the react bindings with tsd but when I run tsc, I get this error. It looks like I've done everything right, so why the error?
So what I eventually figured out was that I need to explicitly include the typings file in my list of "files", i.e.,
{
"version": "1.6.2",
"compilerOptions": {
...
},
"files": [
"foo.ts",
"../typings/react/react.d.ts"
]
}
In other words, I had to include the typings files explicitly in the "files". I don't really know why. I thought tsc was smart enough to look for them itself.
If there is a better solution that doesn't involve having to list all the .d.ts files explicitly in "files", I'm all ears. But I just wanted to point out that this is at least a workaround.