Cannot find name 'FontFace'. TS2304 - javascript

I am trying to load fonts dynamically for my project. I dont understand why I'm getting this error.
"Cannot find name 'FontFace'. TS2304"
Following is the code for your reference:
const loadFont = (name: string, source: string) => {
const font = new FontFace(name, `url(${source})`);
font
.load()
.then(function (loadedFont: any) {
document.fonts.add(loadedFont);
document.body.style.fontFamily = name;
})
.catch(function (error) {
console.log(error);
});
};

If you are using Typescript, make sure you have installed type definitions for CSS Font loading modules
npm install --save #types/css-font-loading-module
Ref: https://www.npmjs.com/package/#types/css-font-loading-module

after installing also you should add type to tsconfig.json, otherwise it will not work.
{
"compilerOptions": {
/* other compiler options... */
"types": ["css-font-loading-module"]
}
}

Related

Problem with parsing javascript file marked as Shebang

I have a react app where I wanted to import a javascript file from a third-party library but file is mark with shebang #!/usr/bin/env node.
I found (e.g. here How to Configure Webpack with Shebang Loader to Ignore Hashbang Importing Cesium React Component into Typescript React Component) I can load file by overriding webpack configuration and adding a new loader shebang-loader (I also have tried shebang-loader2) but overriding webpack in react app is recommended only with #craco/craco so I added it to package.json and tried add loader to existing webpack-config.js.
I produced this lines of code. File craco.config.js:
const throwError = (message) =>
throwUnexpectedConfigError({
packageName: 'craco',
githubRepo: 'gsoft-inc/craco',
message,
githubIssueQuery: 'webpack',
});
module.exports = {
webpack: {
configure: (webpackConfig, {paths}) => {
const shebangLoader = { test: /node_modules\/npm-groovy-lint\/lib\/groovy-lint.js$/, loader: "shebang-loader" }
const {isAdded: shebangLoaderIsAdded1} = addAfterLoader(webpackConfig, loaderByName('url-loader'), shebangLoader);
if (!shebangLoaderIsAdded1) throwError('failed to add shebang-loader');
return webpackConfig;
},
},
};
It resolves problem with shebang and it ignores #!/usr/bin/env node but now I still get error
Module parse failed: Unexpected token (14:16)
File was processed with these loaders:
* ./node_modules/shebang2-loader/index.js
You may need an additional loader to handle the result of these loaders.
| const { getSourceLines, isErrorInLogLevelScope } = require("./utils");
| class NpmGroovyLint {
> "use strict";
| options = {}; // NpmGroovyLint options
| args = []; // Command line arguments
It looks like it does not recognise "use strict" line.
Can anyone put some suggestions what should be a problem ?
After few hours of investigation, I have finally come to a resolution. Firstly I have to say that there is no option to use NpmGroovyLint in react-like applications that run in browsers because after I resolved mentioned problem up here I figured that NpmGroovyLint uses node libraries as perf_hooks which are not available in a browser enviroment.
But I can post code that resolves the problem described in my question. It was needed to add a plugin to babel-loader named 'plugin-proposal-class-properties'. Here is my snipped of craco config. You can use it as a recipe occasionally.
const {addAfterLoader, getLoaders, loaderByName, removeLoaders, throwUnexpectedConfigError} = require('#craco/craco');
const throwError = (message) =>
throwUnexpectedConfigError({
packageName: 'craco',
githubRepo: 'gsoft-inc/craco',
message,
githubIssueQuery: 'webpack',
});
module.exports = {
webpack: {
configure: (webpackConfig, {paths}) => {
const {hasFoundAny, matches} = getLoaders(webpackConfig, loaderByName('babel-loader'));
if (!hasFoundAny) throwError('failed to find babel-loader');
const {hasRemovedAny, removedCount} = removeLoaders(webpackConfig, loaderByName('babel-loader'));
if (!hasRemovedAny) throwError('no babel-loader to remove');
if (removedCount !== 2) throwError('had expected to remove 2 babel loader instances');
//add plugin proposal class properties to existing babel loader
const propClassOptions = {...matches[1].loader.options, ...{plugins: ["#babel/plugin-proposal-class-properties"]}};
const propClassLoader = {...matches[1].loader, ...{options: propClassOptions}};
const babelLoaderWithPropClassPlugin = {...matches[1], ...{loader: propClassLoader}};
const shebangLoader = {
test: /node_modules\/npm-groovy-lint\/lib\/groovy-lint.js$/,
use: [{loader: 'shebang2-loader'}, {...{loader: require.resolve('babel-loader')}, ...{options: propClassOptions}}]
}
const {isAdded: babelLoaderWithPropClassIsAdded} = addAfterLoader(webpackConfig, loaderByName('url-loader'), matches[0].loader);
if (!babelLoaderWithPropClassIsAdded) throwError('failed to add ts-loader');
const {isAdded: babelLoaderIsAdded} = addAfterLoader(webpackConfig, loaderByName('babel-loader'), babelLoaderWithPropClassPlugin.loader);
if (!babelLoaderIsAdded) throwError('failed to add back babel-loader for non-application JS');
const {isAdded: shebangLoaderIsAdded1} = addAfterLoader(webpackConfig, loaderByName('url-loader'), shebangLoader);
if (!shebangLoaderIsAdded1) throwError('failed to add shebang-loader');
return webpackConfig;
},
},
};

ValidationError: Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema. Next.js

I used create-next-app to create my next.js project boiler plate. But as soon i run npm run dev i get the error:
ValidationError: Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
- configuration[0].node should be one of these:
false | object { __dirname?, __filename?, global? }
-> Include polyfills or mocks for various node stuff.
Details:
* configuration[0].node has an unknown property 'fs'. These properties are valid:
object { __dirname?, __filename?, global? }
-> Options object for node compatibility features.
* configuration[0].node has an unknown property 'devServer'. These properties are valid:
object { __dirname?, __filename?, global? }
-> Options object for node compatibility features.
- configuration[1].node should be one of these:
false | object { __dirname?, __filename?, global? }
-> Include polyfills or mocks for various node stuff.
Details:
* configuration[1].node has an unknown property 'fs'. These properties are valid:
object { __dirname?, __filename?, global? }
-> Options object for node compatibility features.
* configuration[1].node has an unknown property 'devServer'. These properties are valid:
object { __dirname?, __filename?, global? }
-> Options object for node compatibility features.
at validate (C:\Users\crisp\OneDrive\Documents\Next.js\next-startup\nextflix\node_modules\next\dist\compiled\schema-utils3\index.js:1:153657)
at validateSchema (C:\Users\crisp\OneDrive\Documents\Next.js\next-startup\nextflix\node_modules\next\dist\compiled\webpack\bundle5.js:137945:2)
at create (C:\Users\crisp\OneDrive\Documents\Next.js\next-startup\nextflix\node_modules\next\dist\compiled\webpack\bundle5.js:141384:24)
at webpack (C:\Users\crisp\OneDrive\Documents\Next.js\next-startup\nextflix\node_modules\next\dist\compiled\webpack\bundle5.js:141426:32)
at f (C:\Users\crisp\OneDrive\Documents\Next.js\next-startup\nextflix\node_modules\next\dist\compiled\webpack\bundle5.js:98978:16)
at HotReloader.start (C:\Users\crisp\OneDrive\Documents\Next.js\next-startup\nextflix\node_modules\next\dist\server\hot-reloader.js:18:415)
at async DevServer.prepare (C:\Users\crisp\OneDrive\Documents\Next.js\next-startup\nextflix\node_modules\next\dist\server\next-dev-server.js:16:453)
at async C:\Users\crisp\OneDrive\Documents\Next.js\next-startup\nextflix\node_modules\next\dist\cli\next-dev.js:22:1 {
errors: [
{
keyword: 'anyOf',
dataPath: '[0].node',
schemaPath: '#/anyOf',
params: {},
message: 'should match some schema in anyOf',
schema: [Array],
parentSchema: [Object],
data: [Object],
children: [Array]
.....
My next.config.js looks as follows.
module.exports = {
webpack: (config) => {
config.node = {
fs: 'empty'
}
return config
}
};
Nothing has changed yet. This is the default. May you please explain to me why am i getting this error.
Any help input will be appreciated.
Can you check any of the dependecies on Nextjs 11 need to be updated.
In my case updating next-transpile-modules to Version: ^8.0.0 resolved the issue.
You are running webpack 5, which only supports __dirname, __filename and global.
Your config assumes webpack 4, which supports many more properties including Node core libraries.
You need to pick which version of webpack you want to run and make sure that your config matches.
Next.js has now webpack-5 enabled by default.
If you don't wanna switch back to webpack-4 (for obvious reasons), your configuration should look something like this:
module.exports = {
webpack: (config, { isServer }) => {
if (!isServer) config.resolve.fallback.fs = false;
return config;
}
};
I saw the answer you posted, there you are configuring path and url also. But you actually don't need to manually configure them as Next.js handles it for you.
For dns, you may do something like this:
module.exports = {
webpack: (config, { isServer }) => {
if (!isServer) {
const fallback = config.resolve.fallback;
fallback.fs = false;
fallback.dns = function () {
if (!arguments.length) return;
const callback = arguments[arguments.length - 1];
if (callback && typeof callback === 'function') callback(null, '0.0.0.0');
};
// or after installing `node-libs-browser`
// fallback.dns = require.resolve('node-libs-browser/dns');
}
return config;
},
};
Refs:
To v5 from v4 | webpack
Automatic Node.js Polyfills Removed
resolve.fallback
next/build/webpack-config.ts
Webpack 5 Adoption
After JDB's answer i had a clear hint. I configured my next.js app to use webpack4 after reading this. Here is my new next.cofig.js:
module.exports = {
webpack5: false,
webpack: (config) => {
config.node = {
dns: "mock",
fs: "empty",
path: true,
url: false,
};
return config;
},
};
Just update the Node version. I was receiving this error also when I tried to create a new next.js app. I had node version 14.16 installed but it seems Next needs ^14.17.0. After updating to 14.18.0 I created a new next app and it ran fine with the default next.config file.

How do I solve Error importing a css file with next.js?

Error:
./node_modules/quill-emoji/dist/quill-emoji.css
ModuleParseError: Module parse failed: Unexpected character '�' (1:0)
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
(Source code omitted for this binary file)
In _app.js, I have:
import "quill-emoji/dist/quill-emoji.css";
And in next.config.js:
const withCSS = require('#zeit/next-css');
const withImages = require("next-images");
const withPlugins = require("next-compose-plugins");
if (typeof require !== 'undefined') {
require.extensions['.less'] = () => {};
require.extensions['.css'] = file => {};
}
module.exports = withPlugins([
withImages,
withCSS
], {
devIndicators: {
autoPrerender: false,
},
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
...
})
The emoji css seems to include content of data:image and loads svg's inline.
I was trying with multiple loaders and couldn't find the right sequence, you probably need resolve-url-loader in some specific sequence.
It maybe best to just link it using next/head and call it a day.
I think the emoji icons are svg. You might need an svg loader to solve this problem.
next-images adds support for jpg, jpeg, svg, png, ico, webp and gif images.
NOTE: I have not tested this with quill
This is an example snippet.
const withImages = require("next-images");
module.exports = withImages({
webpack(config, options) {
return config;
}
});

How to translate Javascript require to Typescript import with const

I'm trying to import faktory (github.com/jbielick/faktory_worker_node).
The README suggests:
const faktory = require('faktory-worker');
faktory.register('ResizeImage', async ({ id, size }) => {
const image = await Image.find(id);
await image.resize(size);
});
faktory.work();
And I tried to translate it to Typescript:
import faktory from 'faktory-worker';
faktory.register('ResizeImage', async ({ id, size }) => {
const image = await Image.find(id);
await image.resize(size);
});
faktory.work();
I keep getting TypeError: Cannot read property 'register' of undefined no matter what I do.
I thought I have to use const to somehow create an object but I just cannot figure out how.
I can keep the syntax but Typescript suggest best practice of import by the rule no-var-requires: require statement not part of an import statement
I think you have to implement typescript definitions of that module too: index.d.ts
E.G. save that file to folder typings in root and add the following to tsconfig.json:
{
"compilerOptions": {
"typeRoots" : ["./typings"]
}
}
This will include the interfaces and register the methods.
There are other possibilities to achieve that #types, typeRoots and types
Adding "esModuleInterop": true to tsconfig.json resolved this issue for me, e.g.
{
"compilerOptions": {
"esModuleInterop": true
// ...
}
}

Systemjs-Builder - Cannot configure properly - Bundling Typescript into a package

I want to build a quick nodejs script to package a Typescript app as SystemJS modules, a lot like what Angular2 bundles look like.
I tried different configurations but I can't seem to put my finger on it, and haven't found clear enough documentation as of yet.
Note that for this "test", I am not using Gulp or Jspm at all, just systemjs-builder for the time being (and don't plan on using jspm at all either)
Here's what my "project" looks like:
---- Project's Root
-------- index.ts // export * from './modules/index' and eventually more
-------- modules
------------ index.ts // export * from './menu/index'
------------ menu
---------------- menu.component.ts // export class
---------------- menu.service.ts // export class
I want to package this under a single file, where I will have multiple SystemRegister modules that can be consumed in an app thereafter
I tried the following without success:
var Builder = require('systemjs-builder');
// optional constructor options
// sets the baseURL and loads the configuration file
var builder = new Builder('./modules');
builder.bundle('./modules/index.ts', {
/* SystemJS Configuration Here */
baseURL: './modules',
transpiler: 'typescript',
typescriptOptions: {
"module": "system",
"emitDecoratorMetadata": true,
"experimentalDecorators": true
},
defaultExtension: 'ts',
packages: {
'modules': {
defaultExtension: 'ts'
}
}
}, 'infrastructure.js')
.then(function() {
console.log('Build complete');
})
.catch(function(err) {
console.error(err);
})
First of all, the defaultExtension options doesn't seem to work at all
So when I do import {something} from 'filePath'; (without extension), it tries to load filePath, instead of filePath.ts;
Second, if I try adding the .ts extension in my imports (which I don't want to do), it complains that the code is invalid (unexpected token #, unexpected token menuItem and so forth)
Anyone have a good example or some explanations on how this is supposed to work?
Thank you
here you have an example: angular typescript skeleton
build task looks like this:
const path = require('path');
const Builder = require('jspm').Builder;
const builder = new Builder();
const packageJson = require(path.join(config.projectDir, 'package.json'));
return beginBuild()
.then(buildSFX)
.catch((err) => console.log('Build Failed', err));
function beginBuild() {
builder.reset();
return builder.loadConfig(path.join(config.projectDir, packageJson.jspm.configFile))
}
function buildSFX() {
const appName = packageJson.name;
const distFileName = `${appName}.min.js`;
const outFile = path.join(config.distDir, distFileName);
const moduleName = 'app';
const buildConfig = {
format: 'global',
minify: true,
sourceMaps: true
};
return builder.buildStatic(moduleName, outFile, buildConfig);
}
and jspm conf looks like this:
System.config({
defaultJSExtensions: true,
transpiler: "typescript",
typescriptOptions: {
"tsconfig": "src/tsconfig.json"
},
paths: {
"github:*": "vendor/jspm_packages/github/*",
"npm:*": "vendor/jspm_packages/npm/*",
"app": "src/index"
}
/// ...
}
Why do you want to bundle typescript? Bundling is a method used for optimizing the delivery of source code to the browser. The browser doesn't know typescript, it only knows javascript (unless you do on the fly transpiling).

Categories