简体   繁体   中英

How can I get webpack to find angular modules?

I'm trying to setup a bare-bones application with Angular 1 + Typescript 2 and Webpack. The app works fine until I try to use an external module, ex: angular-ui-router .

It always complains that it can't find the dependency:

ERROR in ./src/app.ts Module not found: Error: Cannot resolve module 'angular-ui-router' in ./src/app.ts 3:26-54

Demo showing problem: https://github.com/jxc876/angular-ts

I suspect I'm not importing the routing dependency correctly, tried:

  • import uiRouter from 'angular-ui-router';
  • import * as uiRouter from 'angular-ui-router'

Tried with angular-route and also ui-router but neither works. Tried ts-loader and awesome-typescript-loader .

App

import * as angular from 'angular';
import uiRouter from 'angular-ui-router';

let myApp = angular.module('myApp', [uiRouter]);

myApp.config(function($stateProvider) {
  let homeState = {
    name: 'home',
    url: '/home',
    template: '<div>It works !!!</div>'
  }

  $stateProvider.state(homeState);
});

Config

package.json

{
  "name": "ts-demo",
  "scripts": {
    "start": "webpack-dev-server --content-base ./src"
  },
  ...
  "devDependencies": {
    "@types/angular": "^1.5.16",
    "@types/angular-ui-router": "^1.1.34",
    "awesome-typescript-loader": "^3.0.0-beta.3",
    "typescript": "^2.0.9",
    "webpack": "^1.13.3",
    "webpack-dev-server": "^1.16.2"
  },
  "dependencies": {
    "angular": "^1.5.8",
    "angular-ui-router": "^0.3.1",
    "enhanced-resolve": "^2.3.0"
  }
}

webpack.config.js

module.exports = {
  entry: './src/app',
  output: {
    filename: './dist/bundle.js'
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.jsx']
  },
  devtool: 'source-map',
  module: {
    loaders: [
      {
        test: /\.ts$/,
        loader: 'awesome-typescript-loader'
      }
    ]
  }
};

tsconfig.json

{
    "compilerOptions": {
        "outDir": "./dist/",
        "allowJs": true,
        "target": "es5",
        "module": "commonjs",
        "moduleResolution": "node",
        "strictNullChecks": true,
        "listFiles": true
    },
    "include": [
        "./src/**/*"
    ],
      "exclude": [
        "node_modules"
    ]
}

Finally figured this out.

First issue is that the typescript compiler removes import statements that are not used.

The compiler detects whether each module is used in the emitted JavaScript. If a module identifier is only ever used in type annotations and never as an expression then no require call is emitted for that module. This culling of unused references is a good performance optimization, and also allows for optional loading of those modules.

source: https://github.com/Microsoft/TypeScript/issues/4717

I assigned the imported value to a dummy array and it seems to fix this. Logging the value out to the console also works. (See my final note on why I couldn't simply pass it into the dependency array).

EDIT: Better solution is to use import "module"; syntax import "module"; syntax since that is always emitted based on the github above, ex: import 'angular-ui-router';


Second, my webpack file was missing an empty string in the resolve array:

resolve { extensions: ['', '.ts', '.js'] }

Without this it couldn't pull in the file for ui router.

A few things I noticed while working on this: webpack --display-error-details is super useful. For some reason it was looking for double .js.js extensions inside node_modules/angular-ui-router/release :

resolve file
  /Users/mich2264/projects/angular-ts/node_modules/angular-ui-router/release/angular-ui-router.js.ts doesn't exist
  /Users/mich2264/projects/angular-ts/node_modules/angular-ui-router/release/angular-ui-router.js.js doesn't exist

--traceResolution is equally useful for typescript.

EDIT: Appears to be a awesome-typescript-loader loader bug: https://github.com/s-panferov/awesome-typescript-loader/pull/264


Finally, I'm not sure why but when I import the default value from angular-ui-router and I log it or set a breakpoint it shows up correctly as ui.router , but if I attempt to pass it into the dependency array it becomes undefined.

@types/angular-ui-router defines the following export inside their type file : export default "ui.router";

This one should do the job:

import * as angular from 'angular';
import * as uiRouter from 'angular-ui-router';

let myApp = angular.module('myApp', ['ui.router']);

Notice, that import is just importing router code and in application module you need to inject 'ui.router' string.

I suppose that since I'm using UI-Router for AngularJS (1.x) , I had to use...

import '@uirouter/angularjs'

...instead of...

 
 
 
  
  import 'angular-ui-router'
 
  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM