Typescript Definition Files in Webpack - node.js

Okay, so I have a Typescript definition file model.d.ts. It contains definitions for the classes used in my business logic, so that I can have strong typing in my Vue.js files.
I have a Vue.js template person.vue, with a code section that looks like this:
<script lang="ts">
import axios from "axios";
import * as _ from "lodash";
import * as model from "model";
// ...
</script>
But when I try to build this with Webpack, I run into problems:
ERROR in I:\git\myapp\src\component\person-page\person.vue.ts
[tsl] ERROR in I:\git\myapp\src\component\person-page\person.vue.ts(27,24)
TS2307: Cannot find module 'model'.
ERROR in ../myapp/node_modules/ts-loader!../myapp/node_modules/vue-loader/lib/selector.js?type=script&index=0&bustCache!../myapp/src/component/person-page/person.vue
Module not found: Error: Can't resolve 'model' in 'I:\git\myapp\src\component\person-page'
# ../myapp/node_modules/ts-loader!../myapp/node_modules/vue-loader/lib/selector.js?type=script&index=0&bustCache!../myapp/src/component/person-page/person.vue 10:14-30
# ../myapp/src/component/person-page/person.vue
# ../myapp/src/main.ts
# multi webpack-hot-middleware/client ./src/main.ts
I'm using ts-loader, and the relevant parts of my webpack.config.js look like this:
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /.ts$/,
use: {
loader: "ts-loader", options: {
appendTsSuffixTo: [/\.vue$/]
}
},
exclude: /node_modules/
},
// ...
{
test: /\.vue$/,
loader: "vue-loader"
}
]
},
resolve: {
extensions: [".ts", ".js", ".vue", ".json"],
alias: {
"vue$": "vue/dist/vue.esm.js"
}
}
};
Why doesn't my definition file work, and how can I make it so that it can be used in person.vue?

I think you have a problem with your path. "model" should point to the complete path to the model.d.ts without the file extensions.

Related

Node.js: How to import test files in custom test runner

I'm trying to create my own custom testing framework for learning purpose. Test files are written in following way
import { somemethod } from './some/module'
test(/I click on a button)/, () => {
browser.get("someSelector").should("have.text",somemethod());
});
I user require(file) to load test files. But it throw error SyntaxError: Unexpected token {
for import statement in test file. I'm using node js version 11.15.
If I switch to node v13.14 and define "type": "module" in my package.json then it doesn't let me use require(file) to load a test file or any module in my package.
How can I import tests files considering the user may be importing the modules using import or require?
This answer is very empirical...
Considering that it works using canonical commonjs approach you can try to debug it with newer version of NODE (currently I would use 14). For it, I would suggest you to use a node version manager like NVM so you can switch between node version easily and test that accordling seeing differences between various node installations.
Make a minimal project with npm init with a single dependency, save your index with the .mjs extension and try an import the above dependency. If you are be able to import that dependency with that minimal environment you can blame either your previous node or your configuration or both of them.
At the moment you should only create a small 2 files project to reproduce the problem. It seems your current node does not consider the "type": "module" configuration and runs everything in its classic way.
Regarding your comments....
As far as I know import can be used even in your code, not just at the beginning:
(async () => {
if (somethingIsTrue) {
// import module for side effects
await import('/modules/my-module.js');
}
})();
from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
Additionally you can try Webpack with a configuration like:
// webpack.config.js
const nodeExternals = require('webpack-node-externals');
module.exports = {
mode: 'production',
target: 'node',
externals: [nodeExternals()],
entry: {
'build/output': './src/index.js'
},
output: {
path: __dirname,
filename: '[name].bundle.js',
libraryTarget: 'commonjs2'
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
['env', {
'targets': {
'node': 'current'
}
}]
]
}
}
}]
}
};
With NodeExternals you don't put your node dependencies in the bundle but only your own code. You refer to node_modules for the rest. You might not want that.

Webpack file-loader with sass-loader

I am new to nodejs and get a problem when trying to use sass with it.
The following information is just fictional, but it represents the
actual condition.
THE SCENARIO:
I have the following folder structure:
frontend/
- scss/
- style.scss
- main.js
webpack.config.js
Goal:
I want to compile the style.scss to style.css using webpack and put it inside dist/frontend/css/ directory, so it should be resulting this path: dist/frontend/css/style.css and create the following folder structure:
dist/
- frontend/
- scss/
- style.scs
- main.js
frontend/
- scss/
- style.scss
- main.js
webpack.config.js
THE CODES:
main.js
import `style from "./scss/style.scss";`
webpack.config.js
module.exports = {
mode: "development",
entry: {
main: "./frontend/main.js"
},
output: {
path: path.join(__dirname, "/dist/frontend"),
publicPath: "/",
filename: "[name].js"
},
module: {
rules: [
{
test: /\.(s*)css$/,
use: [
{
loader: "file-loader",
options: {
name: "css/[name].[ext]"
}
},
"style-loader/url",
"css-loader?-url",
"sass-loader"
]
}
]
}
THE RESULT:
I get this message:
Module not found: Error: Can't resolve './scss/style.scss' in 'E:\project_name\frontend'
THE QUESTIONS
Why is that happening?
What is the correct codes to achieve the Goal?
As the message said, this path is not valid: './scss/style.scss'. There are typo when defining the path. The folder is supposed to be sass instead of scss.
The following configuration will work to achieve the Goal mentioned in the question:
module: {
rules: [
{
test: /\.(s*)css$/,
use: [
"style-loader/url",
{
loader: "file-loader",
options: {
name: "css/[name].css"
}
},
"sass-loader"
]
}
]
}
It works like Mini CSS Extract Plugin, but does not generating additional .js files for each .css file when used to convert multiple .scss files into different .css files.

How to use relative paths with node-loader and native addon

I have a native addon I am using that works great on my dev machine but fails on any other machine due to the webpack build using an absolute path to the native module instead of a relative one. Here is the error I get:
/main.prod.js:7543: Uncaught Error: Cannot open /Users/.../app/lib/main.node: Error: dlopen(/Users/.../app/lib/main.node, 1): image not found
In my main.dev.js I import the file like this: import main from './lib/main.node';
In webpack config I have added a module test for .node:
export default {
externals: Object.keys(externals || {}),
module: {
rules: [{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true
}
}
}, {
test: /\.node$/,
use: 'node-loader'
}]
},
...
How can I make sure that my main.node file gets packaged for the build and imported via relative path?
I was able to resolve this issue by switching to a modified version of node-addon-loader. https://github.com/smt116/node-native-ext-loader

Loading a static file in Angular during build

I'm want to load the contents of a file and inject it as a string in TypeScript at build time. I understand that this code would ordinarily be server code, but what I want is to have a build step that reads the file and injects its contents as a string.
import { readFileSync } from 'fs';
import { Component } from '#angular/core';
#Component({
template: `<pre>${readFileSync('./example.code')}</pre>`
})
export class ExampleComponent { }
Assuming example.code just has "Hello World" I would want this file to be built as:
template: `<pre>"Hello World"</pre>`
I have found babel-plugin-static-fs which I think should allow me to do this, but I was originally using ng (angular-cli) to build the project. I have done ng eject and updated webpack:
module: {
rules: [
/* snip */
{
"test": /\.ts$/,
"use": [
{
loader: "babel-loader",
options: {
plugins: ['babel-plugin-static-fs']
}
},
{
"loader": "#ngtools/webpack"
}, ] } ] }
However, when I run webpack, I still get
Cannot find module 'fs'
If I reverse the order of the loaders, it seems like babael does not like the # used in may annotations such as the #Component above so that loader does not work.
Is there any way to load a file as static content during an Angular project build?
The issue here is actually related to the tsconfig.app.json file that Angular creates and uses for AoT. This is separate from the tsconfig.json used to actually build the project which does load #types/node as expected.
If you've created a project with ng new, you can change tsconfig.app.json:
- "types": [],
+ "types": ["node"],
This will have the AoT compiler use the type definitions from #types/node.

"You may need an appropriate loader for this file type", webpack can't parse angular2 file

I'm trying to get a very simple Angular2 app working, with Webpack as a module bundler. I'm following this code, and I copied all the configuration files as they are, only changing file paths. However, when I run npm-start, I get the following error, which I think is a Webpack error:
ERROR in ./hello.js
Module parse failed: /home/marieficid/Documentos/cloud/cloud/hello.js Line 1: Unexpected token
You may need an appropriate loader to handle this file type.
| import {bootstrap} from "angular2/platform/browser";
| import {Component} from "angular2/core";
|
# ./app.ts 2:0-21
As a result, the Angular2 code in my app isn't loaded.
This is my app.ts:
import "./hello.js";
This is hello.js, where the error seems to be (which I take to mean that webpack parsed app.ts just fine):
import {bootstrap} from "angular2/platform/browser";
import {Component} from "angular2/core";
#Component({
selector: 'app',
template: '<div>Hello world</div>'
})
class App{}
bootstrap(App);
And this iswebpack.config.js:
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var path = require('path');
module.exports = {
entry: {
'app': './app.ts',
'vendor': './vendor.ts'
},
output: {
path: "./dist",
filename: "bundle.js"
},
plugins: [
new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.bundle.js'),
new HtmlWebpackPlugin({
inject: false,
template: './index.html'
})
],
resolve: {
extensions: ['', '.ts', '.js']
},
module: {
loaders: [
{ test: /\.ts$/, loader: 'ts-loader' },
],
noParse: [ path.join(__dirname, 'node_modules', 'angular2', 'bundles') ]
},
devServer: {
historyApiFallback: true
}
};
All these files and node_modules are in the same directory.
I have found similar questions online but nothing worked for me. I also didn't install babel because the sample code I'm using as base doesn't use it, but if it's necessary I'm will.
As suggested by #napstablook
Since in your webpack.config.js file you have
resolve: {
extensions: ['', '.ts', '.js']
},
Webpack will try to handle those .js files but it needs a specific loader to do so which is, if I'm not wrong, script-loader.
In your case the solution is as simple as deleting the .js files, or changing their extension to be .ts.
For me this issue occurred when I ran ng test,
please check below points,
Console will list out the files that is causing the error.
Check the html file is correctly mapped from the typescript.
styleUrls file should point to the CSS file not html, this is the mistake I
did.
this error also comes up for me in angular forms when i had patch value set then an extra = sign
ncont.controls[position].patchValue({[cardname]:file}) = file
which is a dumb part on me and angular for not telling me

Resources