Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4: "Cannot find name 'require'

I am building an app with Angular 4 and webpack.

I have the following in one of my components:

ngOnInit() {     require('/assets/js/regular-expresions.js'); } 

When I attempt to compile, I get:

ERROR in C:/SRC/Sandbox/eat-sleep-code.com/src/app/content.component.ts (21,9): Cannot find name 'require'.

I have ran npm install @types/node --save-dev and updated my tsconfig.json to look like:

{   "compileOnSave": false,   "compilerOptions": {     "outDir": "./dist/out-tsc",     "baseUrl": "src",     "sourceMap": true,     "declaration": false,     "moduleResolution": "node",     "emitDecoratorMetadata": true,     "experimentalDecorators": true,     "target": "es5",     "types": [       "node"     ],     "typeRoots": [       "node_modules/@types"     ],     "lib": [       "es2016",       "dom"     ]   } } 

But alas, the same error keeps getting thrown. Any ideas?


Here is my package.json:

{   "name": "eat-sleep-code.com",   "version": "0.0.0",   "license": "MIT",   "scripts": {     "ng": "ng",     "start": "ng serve",     "build": "ng build",     "test": "ng test",     "lint": "ng lint",     "e2e": "ng e2e"   },   "private": true,   "dependencies": {     "@angular/animations": "^4.0.1",     "@angular/common": "^4.0.0",     "@angular/compiler": "^4.0.0",     "@angular/core": "^4.0.0",     "@angular/forms": "^4.0.0",     "@angular/http": "^4.0.0",     "@angular/material": "^2.0.0-beta.3",     "@angular/platform-browser": "^4.0.0",     "@angular/platform-browser-dynamic": "^4.0.0",     "@angular/router": "^4.0.0",     "@types/node": "^6.0.69",     "angularfire2": "^2.0.0-beta.8",     "core-js": "^2.4.1",     "firebase": "^3.7.8",     "jquery": "^3.2.1",     "jquery-validation": "^1.16.0",     "ng2-gist": "^1.0.0",     "promise-polyfill": "^6.0.2",     "requirejs": "^2.3.3",     "rxjs": "^5.1.0",     "typescript": "^2.2.2",     "web-animations-js": "^2.2.4",     "webpack": "^2.4.1",     "zone.js": "^0.8.4"   },   "devDependencies": {     "@angular/cli": "1.0.0",     "@angular/compiler-cli": "^4.0.0",     "@types/jasmine": "2.5.38",     "@types/node": "^6.0.69",     "codelyzer": "~2.0.0",     "jasmine-core": "~2.5.2",     "jasmine-spec-reporter": "~3.2.0",     "karma": "~1.4.1",     "karma-chrome-launcher": "~2.0.0",     "karma-cli": "~1.0.1",     "karma-coverage-istanbul-reporter": "^0.2.0",     "karma-jasmine": "~1.1.0",     "karma-jasmine-html-reporter": "^0.2.2",     "protractor": "~5.1.0",     "ts-node": "~2.0.0",     "tslint": "~4.5.0",     "typescript": "^2.2.2",     "webpack": "^2.4.1"   } } 
like image 877
eat-sleep-code Avatar asked Apr 18 '17 15:04

eat-sleep-code


People also ask

Can I use require in angular?

require() is internal to NodeJS and not available to users of Angular CLI if I am not mistaken. I cannot use this code as it fails.

Can not find module path?

To solve the "Cannot find module path or its corresponding type declarations" error, install the types for node by running the command npm i -D @types/node . You can then import path with the following line of code import * as path from 'path' .


2 Answers

Try adding declare var require: any; on top.

like image 70
Ron FND Avatar answered Sep 23 '22 06:09

Ron FND


require() is not advisable for a few reasons. One, it will "break" the effectiveness of tree-shaking in webpack 2 and two, it will prevent proper code splitting.

A far better alternative is to use webpack's implementation of System.import:

System.import('/assets/js/regular-expresions.js').then(file => {    // perform additional interactions after the resource has been asynchronously fetched }); 

In order to satisfy the Typescript compiler (as you have found), you will need to tell it that System is an acceptable variable by declaring it:

declare var System: any;     

You can either add this line to your component if you only intend to reference it once, or you can add it to the typings.d.ts type definition file to enable its use throughout your app. Note that if you change the typings file, you will need to restart the ng serve session.

This satisfies the compiler at build time and it gets hijacked at runtime by the build system, patching the call through into Webpack's System.import.

Webpack in turn will check to see if it has a chunk that satisfy the requested file and, if it does not, it will dynamically create a script tag and insert it into the head, loading the file with the async attribute, which is what occurs in this case.

Once the file loads, it will be parsed and executed. However, if you want to interact with any part of it via the async .then() callback, your file will need to export anything you wish to invoke, such as:

export function test() {     console.log('we called test'); } 

This will expose the .test() function to your callback handler:

System.import('/assets/js/regular-expresions.js').then(file => {    file.test(); }); 
like image 29
David L Avatar answered Sep 26 '22 06:09

David L