2016-12-09 86 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

这违背了使用模块 –