4.24.2017

Подключаем uikit 3.0.0-21-beta к проекту на TypeScript или TS7016: Could not find a declaration file for module 'uikit/dist/js/uikit'. '/node_modules/uikit/dist/js/uikit.js' implicitly has an 'any' type.

Хотел бы поделиться решением вопроса, как подключить uikit 3.0.0-21.beta к проекту на typescript и webpack. В данном деле может возникнуть 3 небольших сложности: первая, как правильно импортировать uikit, второе, где взять типы для uikit и третье, почему все равно не работает.
 
Для тех кто еще не слышал о uikit скажу, что это модульный фреймворк для  разработки быстрых и мощных веб-интерфейсов.

Чтобы узнать как подключить  uikit используя webpack можно обратиться к официальной документации https://getuikit.com/docs/webpack, там описан следующий способ:
 
import UIkit from 'uikit';
 
Но в данном случае компилятор TypeScript будет ругаться и подключить нормально uikit не даст, чтоб все таки подключить фреймворк нужно использовать следующий код:

import * as UIkit from 'uikit';
import * as Icons from 'uikit/dist/js/uikit-icons';

UIkit.use(Icons);

UIkit.notification('Hello world.');

Теперь все работает но компилятор TypeScript продолжает ругаться. Это происходит потому, что он не находит типы для uikit. Поэтому скачаем их:

npm install --save @types/uikit

Вроде все что нужно для работы у нас есть, но компилятор TypeScript продолжает упорно ругаться. На этот раз все происходит не по нашей вине, просто текущая версия типов не описывает модули которые нам нужны.

Для того, чтобы все окончательно заработало нужно описать недостающие типы. Я это уже сделал, и отправил pull request на DefinitelyTyped. 
Это первый мой pull request подобного рода, надеюсь пройдет :)


Итоговый код:

Описание недостающих типов для репозитория https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/uikit на состояние 24.04.2017

type fn = (arg: any) => any;

interface Icons {
    album: HTMLObjectElement;
    ban: HTMLObjectElement;
    behance: HTMLObjectElement;
    bell: HTMLObjectElement;
    bold: HTMLObjectElement;
    bolt: HTMLObjectElement;
    bookmark: HTMLObjectElement;
    calendar: HTMLObjectElement;
    camera: HTMLObjectElement;
    cart: HTMLObjectElement;
    check: HTMLObjectElement;
    clock: HTMLObjectElement;
    close: HTMLObjectElement;
    code: HTMLObjectElement;
    cog: HTMLObjectElement;
    comment: HTMLObjectElement;
    commenting: HTMLObjectElement;
    comments: HTMLObjectElement;
    copy: HTMLObjectElement;
    database: HTMLObjectElement;
    desktop: HTMLObjectElement;
    download: HTMLObjectElement;
    dribbble: HTMLObjectElement;
    expand: HTMLObjectElement;
    facebook: HTMLObjectElement;
    file: HTMLObjectElement;
    flickr: HTMLObjectElement;
    folder: HTMLObjectElement;
    forward: HTMLObjectElement;
    foursquare: HTMLObjectElement;
    future: HTMLObjectElement;
    github: HTMLObjectElement;
    gitter: HTMLObjectElement;
    google: HTMLObjectElement;
    grid: HTMLObjectElement;
    happy: HTMLObjectElement;
    hashtag: HTMLObjectElement;
    heart: HTMLObjectElement;
    history: HTMLObjectElement;
    home: HTMLObjectElement;
    image: HTMLObjectElement;
    info: HTMLObjectElement;
    instagram: HTMLObjectElement;
    italic: HTMLObjectElement;
    joomla: HTMLObjectElement;
    laptop: HTMLObjectElement;
    lifesaver: HTMLObjectElement;
    link: HTMLObjectElement;
    linkedin: HTMLObjectElement;
    list: HTMLObjectElement;
    location: HTMLObjectElement;
    lock: HTMLObjectElement;
    mail: HTMLObjectElement;
    menu: HTMLObjectElement;
    minus: HTMLObjectElement;
    more: HTMLObjectElement;
    move: HTMLObjectElement;
    nut: HTMLObjectElement;
    pagekit: HTMLObjectElement;
    pencil: HTMLObjectElement;
    phone: HTMLObjectElement;
    pinterest: HTMLObjectElement;
    play: HTMLObjectElement;
    plus: HTMLObjectElement;
    pull: HTMLObjectElement;
    push: HTMLObjectElement;
    question: HTMLObjectElement;
    receiver: HTMLObjectElement;
    refresh: HTMLObjectElement;
    reply: HTMLObjectElement;
    rss: HTMLObjectElement;
    search: HTMLObjectElement;
    server: HTMLObjectElement;
    settings: HTMLObjectElement;
    shrink: HTMLObjectElement;
    social: HTMLObjectElement;
    soundcloud: HTMLObjectElement;
    star: HTMLObjectElement;
    strikethrough: HTMLObjectElement;
    table: HTMLObjectElement;
    tablet: HTMLObjectElement;
    tag: HTMLObjectElement;
    thumbnails: HTMLObjectElement;
    trash: HTMLObjectElement;
    tripadvisor: HTMLObjectElement;
    tumblr: HTMLObjectElement;
    tv: HTMLObjectElement;
    twitter: HTMLObjectElement;
    uikit: HTMLObjectElement;
    unlock: HTMLObjectElement;
    upload: HTMLObjectElement;
    user: HTMLObjectElement;
    users: HTMLObjectElement;
    vimeo: HTMLObjectElement;
    warning: HTMLObjectElement;
    whatsapp: HTMLObjectElement;
    wordpress: HTMLObjectElement;
    world: HTMLObjectElement;
    xing: HTMLObjectElement;
    yelp: HTMLObjectElement;
    youtube: HTMLObjectElement;
    "arrow-down": HTMLObjectElement;
    "arrow-left": HTMLObjectElement;
    "arrow-right": HTMLObjectElement;
    "arrow-up": HTMLObjectElement;
    "chevron-down": HTMLObjectElement;
    "chevron-left": HTMLObjectElement;
    "chevron-right": HTMLObjectElement;
    "chevron-up": HTMLObjectElement;
    "cloud-download": HTMLObjectElement;
    "cloud-upload": HTMLObjectElement;
    "credit-card": HTMLObjectElement;
    "file-edit": HTMLObjectElement;
    "git-branch": HTMLObjectElement;
    "git-fork": HTMLObjectElement;
    "github-alt": HTMLObjectElement;
    "google-plus": HTMLObjectElement;
    "minus-circle": HTMLObjectElement;
    "more-vertical": HTMLObjectElement;
    "paint-bucket": HTMLObjectElement;
    "phone-landscape": HTMLObjectElement;
    "play-circle": HTMLObjectElement;
    "plus-circle": HTMLObjectElement;
    "quote-right": HTMLObjectElement;
    "sign-in": HTMLObjectElement;
    "sign-out": HTMLObjectElement;
    "tablet-landscape": HTMLObjectElement;
    "triangle-down": HTMLObjectElement;
    "triangle-left": HTMLObjectElement;
    "triangle-right": HTMLObjectElement;
    "triangle-up": HTMLObjectElement;
    "video-camera": HTMLObjectElement;
}

declare namespace UIkit {
    const use: fn;
    const notification: fn;
}

declare let Icons: Icons;

declare module "uikit" {
    export = UIkit;
}

declare module "uikit/dist/js/uikit" {
    export = UIkit;
}

declare module "uikit/dist/js/uikit-icons" {
    export = Icons;
}

4.23.2017

Angular 2 webpack: WARNING in ./~/@angular/core/@angular/core.es5.js 5870:15-36 Critical dependency: the request of a dependency is an expression

Проблема с предупреждением о критической зависимости  (Critical dependency) может возникать как с angular 2 + webpack так и с angular 4 + webpack. Данная проблема в большинстве случаев связанна с контекстом вывоза и решается при помощи плагина ContextReplacementPlugin.

В своем проекте я использую следующее окружение, package.json:

"dependencies": {
  "@angular/common": "~4.0.0",
  "@angular/compiler": "~4.0.0",
  "@angular/compiler-cli": "~4.0.0",
  "@angular/core": "~4.0.0",
  "@angular/forms": "~4.0.0",
  "@angular/http": "~4.0.0",
  "@angular/platform-browser": "~4.0.0",
  "@angular/platform-browser-dynamic": "~4.0.0",
  "@angular/platform-server": "~4.0.0",
  "@angular/router": "~4.0.0",
  "@angular/tsc-wrapped": "~4.0.0",
  "@angular/upgrade": "~4.0.0",
  "@ngrx/core": "^1.2.0",
  "@ngrx/effects": "^2.0.3",
  "@ngrx/store": "^2.2.2",
  "angular-in-memory-web-api": "~0.3.1",
  "core-js": "^2.4.1",
  "rxjs": "5.0.1",
  "zone.js": "^0.8.4"},
"devDependencies": {
  "@types/core-js": "^0.9.41",
  "@types/jasmine": "2.5.36",
  "@types/node": "^6.0.45",
  "angular2-template-loader": "^0.6.0",
  "awesome-typescript-loader": "^3.0.4",
  "css-loader": "^0.26.1",
  "css-to-string-loader": "^0.1.2",
  "extract-text-webpack-plugin": "^2.1.0",
  "file-loader": "^0.9.0",
  "html-loader": "^0.4.4",
  "html-webpack-plugin": "^2.24.1",
  "jasmine": "~2.4.1",
  "jasmine-core": "~2.4.1",
  "karma": "^1.3.0",
  "karma-chrome-launcher": "^2.0.0",
  "karma-cli": "^1.0.1",
  "karma-jasmine": "^1.0.2",
  "karma-jasmine-html-reporter": "^0.2.2",
  "karma-phantomjs-launcher": "^1.0.2",
  "karma-sourcemap-loader": "^0.3.7",
  "karma-webpack": "^2.0.1",
  "lodash": "^4.16.2",
  "node-sass": "^4.5.2",
  "null-loader": "^0.1.1",
  "phantomjs-prebuilt": "^2.1.7",
  "protractor": "~4.0.14",
  "raw-loader": "^0.5.1",
  "rimraf": "^2.5.4",
  "sass-loader": "^6.0.3",
  "source-map-loader": "^0.1.5",
  "style-loader": "^0.13.1",
  "tslint": "^3.15.1",
  "typescript": "~2.2.0",
  "uikit": "^3.0.0-beta.21",
  "webpack": "^2.4.1",
  "webpack-dev-server": "2.4.1",
  "webpack-merge": "^3.0.0"}

В моем случае первый раз проблема возникла когда я самостоятельно настраивал webpack.config, после чего я решил использовал готовый конфиг с сайта angular.io.


Но данная ошибка возникала даже в скачанном примере:








В поисках решения проблемы я нашел отличный модуль для старта приложения на angular 2/4 - angular 2 starter. Для меня сейчас там слишком много всего, и пока мне требуется решение чуть проще. Итого я решил, что нужно избавиться от данного предупреждения в той конфигурации которую предлагает сайт https://angular.io.

Решение

Рабочим кодом конфигурации для меня стала следующий код:

new webpack.ContextReplacementPlugin(
    /angular(\\|\/)core(\\|\/)@angular/,
    helpers.root('./src'),
    {}
),