2016-12-09 131 views
5

我正在嘗試在我的TypeScript應用程序中使用Fuse。我正在使用import * as fuselib from 'fuse.js';導入模塊類型。這與編號tsc罰款。我遇到的問題是當我使用webpack --config config/webpack.prod.js --progress --profile --bail構建項目時。爲什麼當TypeScript編譯器不能找到一個模塊時,Webpack將無法找到一個模塊?

我收到錯誤Cannot find module 'fuse.js'Fuse類型可以找到here。看着我編譯的JS,我找不到字fuse.js,所以我猜Webpack正在改變這個名字。我試圖忽略UglifyJsPlugin中的關鍵字fuse.js,但這並沒有幫助。

我的Webpack配置非常標準。

webpack.prod.js

var webpack = require('webpack'); 
var webpackMerge = require('webpack-merge'); 
var ExtractTextPlugin = require('extract-text-webpack-plugin'); 
var commonConfig = require('./webpack.common.js'); 
var helpers = require('./helpers'); 

const ENV = process.env.NODE_ENV = process.env.ENV = 'production'; 

module.exports = webpackMerge(commonConfig, { 
    devtool: 'source-map', 

    output: { 
     path: helpers.root('dist'), 
     publicPath: '/', 
     filename: '[name].[hash].js', 
     chunkFilename: '[id].[hash].chunk.js' 
    }, 

    htmlLoader: { 
     minimize: false // workaround for ng2 
    }, 

    plugins: [ 
     new webpack.NoErrorsPlugin(), 
     new webpack.optimize.DedupePlugin(), 
     new webpack.optimize.UglifyJsPlugin({ // https://github.com/angular/angular/issues/10618 
      mangle: { 
       keep_fnames: true, 
       except: ['fuse.js'] 
      } 
     }), 
      new ExtractTextPlugin('[name].[hash].css'), 
      new webpack.DefinePlugin({ 
       'process.env': { 
        'ENV': JSON.stringify(ENV) 
       } 
      }) 
    ] 
}); 

webpack.common.js

var webpack = require('webpack'); 
var HtmlWebpackPlugin = require('html-webpack-plugin'); 
var ExtractTextPlugin = require('extract-text-webpack-plugin'); 
var helpers = require('./helpers'); 

module.exports = { 
    entry: { 
     'polyfills': './src/polyfills.ts', 
     'vendor': './src/vendor.ts', 
     'app': './src/main.ts' 
    }, 

    resolve: { 
     extensions: ['', '.js', '.ts', '.tsx'], 
     modulesDirectories: ['src', 'node_modules'] 
    }, 

    module: { 
     loaders: [ 
     { 
      test: /\.ts$/, 
      loaders: ['awesome-typescript-loader', 'angular2-template-loader', 'angular2-router-loader'] 
     }, 
     { 
      test: /\.html$/, 
      loader: 'html' 
     }, 
      { 
       test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/, 
       loader: 'file?name=assets/[name].[hash].[ext]' 
      }, 
      { 
       test: /\.css$/, 
       exclude: helpers.root('src', 'app'), 
       loader: ExtractTextPlugin.extract('style', 'css?sourceMap') 
      }, 
       { 
        test: /\.css$/, 
        include: helpers.root('src', 'app'), 
        loader: 'raw' 
       } 
     ] 
    }, 

    plugins: [ 
     // for materialize-css 
     new webpack.ProvidePlugin({ 
      "window.jQuery": "jquery", 
      "window._": "lodash", 
      _: "lodash" 
     }), 
     new webpack.optimize.CommonsChunkPlugin({ 
      name: ['app', 'vendor', 'polyfills'] 
     }), 
     new HtmlWebpackPlugin({ 
      template: 'src/index.html' 
     }) 
    ] 
}; 

我是什麼,以便使的WebPack看到模塊fuse.js失蹤?

+0

您是否將其添加到package.json中並執行npm安裝? –

+0

我做過了,入口是'「fuse.js」:「2.6.1」'。 – onetwothree

+0

另請參閱https://github.com/krisk/Fuse/pull/124,其中描述瞭解決方法。 – Arjan

回答

6

好,這裏是正在發生什麼,以及爲什麼。

首先,Fuze/index.d.ts試圖宣佈自己既是一個全局模塊又是一個環境外部模塊,但是這兩者都不正確。這會導致誤用,例如導致您的錯誤幾乎不可避免的錯誤。

它包含一個模塊聲明,其中包含一個類聲明,可能是爲了描述模塊的形狀,但不導出該類。

declare module 'fuse.js' { 
    class Fuze // missing one of: export, export =, export default 
} 

這意味着我無法正確導入模塊,事實上在嘗試從中導入值和/或類型時會出現類型錯誤。

Fuse/index.d.ts再往下就宣佈其全球

declare const Fuse; 

據推測,根據慣例和閱讀在實際的JavaScript的意見,這是爲了有相同的形狀,什麼是從模塊輸出。不幸的是,它有any這是既不是類型的嘗試模塊,因爲它是無效的,也沒有類型Fuse被困在所述模塊內但未導出...

那麼爲什麼錯誤?你可能在你的程序中有以下某處: import'fuse'; 從'保險絲'進口保險絲; 從'fuse'導入*作爲保險絲;

其次是一些使用Fuse

const myFuse = new Fuse(); 

這將導致以打字稿發出保險絲fuse的運行時表示的進口,這樣就可以使用模塊導入的值。

要解決該問題,您可以使用全球const Fuse,而不是任何地方導入它。不幸的是,這不是預期的。筆者幾乎肯定意味着有以下內容Fuze/index.d.ts

export = Fuse; 

export as namespace Fuse; 

declare class Fuse { 
    constructor(list: any[], options?: Fuse.FuseOptions) 
    search<T>(pattern: string): T[]; 
    search(pattern: string): any[]; 
} 

declare namespace Fuse { 
    export interface FuseOptions { 
     id?: string; 
     caseSensitive?: boolean; 
     include?: string[]; 
     shouldSort?: boolean; 
     searchFn?: any; 
     sortFn?: (a: { score: number }, b: { score: number }) => number; 
     getFn?: (obj: any, path: string) => any; 
     keys?: string[] | { name: string; weight: number }[]; 
     verbose?: boolean; 
     tokenize?: boolean; 
     tokenSeparator?: RegExp; 
     matchAllTokens?: boolean; 
     location?: number; 
     distance?: number; 
     threshold?: number; 
     maxPatternLength?: number; 
     minMatchCharLength?: number; 
     findAllMatches?: boolean; 
    } 
} 

它聲明一個類或者是在全球上市,對於那些不使用ES模塊,或通過爲那些誰是一個進口。您可以使用上述UMD樣式聲明來獲得作者所期望的打字體驗。與庫捆綁在一起的軟件沒有提供類型信息,實際使用時會導致錯誤。

考慮向維護人員發送拉取請求並附帶修復程序。

使用

您可以通過以下方式使用此聲明:

CommonJS的打字稿風格

import * as Fuse from 'fuse.js'; 

const myFuseOptions: Fuse.FuseOptions = { 
    caseSensitive: false 
}; 
const myFuse = new Fuse([], myFuseOptions); 

傳統CommonJS的風格

import Fuse = require('fuse.js'); 

const myFuseOptions: Fuse.FuseOptions = { 
    caseSensitive: false 
}; 
const myFuse = new Fuse([], myFuseOptions); 

ES 與CommonJS的互操作風格

(使用"module": "system""allowSyntheticDefaltImportsTrue"時)與SystemJS或者如果通過巴貝爾管道。

import Fuse from 'fuse.js'; 

const myFuseOptions: Fuse.FuseOptions = { 
    caseSensitive: false 
}; 
const myFuse = new Fuse([], myFuseOptions); 
+0

另見https://github.com/krisk/Fuse/pull/124與解釋說明中的解決方法。 – Arjan

+1

例如,使用'fuse.js'的'import {Fuse,FuseOptions};''或'import *'作爲'fuse.js'的fuselib;''用於上面的'index.d.ts',讓我'TS2497 :模塊'「.../node_modules/fuse。js/index「'解析爲非模塊實體,不能使用此構造導入。」任何想法...? – Arjan

+0

好的。我的例子中有一個錯誤,我沒有導出接口以避免污染全局命名空間及其類型名我已經稍微更新了這個例子,它現在可以按預期工作了謝謝 –

0

訣竅是提供對全局變量Fuse的訪問。 它通過的WebPack與ProvidePlugin

完成添加以下插件的插件的WebPack數組:

... 
    new webpack.ProvidePlugin({ 
     "Fuse": "fuse.js" 
    }) 
    ... 
+0

如何在代碼中導入'fuse.js'?我將此行添加到我的webpack配置中,錯誤仍然存​​在。 – onetwothree

+0

@onetwothree:它僅僅是: '進口「fuse.js」;' 有了這條線,你告訴打字稿該模塊可 – Kalle

+0

這違背了使用模塊 –