2015-12-15 42 views
19

我正在使用帶有WebPack和NPM的Zurb Foundation,沒有 Bower。NPM + Zurb Foundation + WebPack:無法解析模塊'foundation'

我遇到的問題是一樣的,因爲這下面:

https://github.com/zurb/foundation-sites/issues/7386

從本質上講,通過安裝NPM基礎的網站的時候,有一個模塊「基礎」未找到引用。錯誤:

Module not found: Error: Cannot resolve module 'foundation' in c:\Users\Matt\Documents\Projects\test\node_modules\foundation-sites\dist 
@ ./~/foundation-sites/dist/foundation.js 

這裏的的package.json:

{ 
    "name": "test", 
    "version": "1.0.0", 
    "description": "", 
    "main": "index.js", 
    "scripts": { 
    "test": "echo \"Error: no test specified\" && exit 1", 
    "dev": "webpack-dev-server" 
    }, 
    "author": "", 
    "license": "ISC", 
    "dependencies": { 
    "foundation-sites": "6.0.5", 
    "webpack": "~1.12.6", 
    "webpack-dev-server": "~1.2", 
    "jquery": "2.1.1" 
    } 
} 

這裏是webpack.config.js:

var path = require("path"); 
var webpack = require("webpack"); 
module.exports = { 
    entry: { 
     main: "./app/js/main.js" 
    }, 
    output: { 
     path: __dirname, 
     filename: "bundle.js" 
    }, 
    module: { 
     loaders: [ 
      { test: /\.css$/, loader: "style!css" }, 
      { 
       test: /\.scss$/, 
       loaders: ["style", "css", "sass"] 
       }, 
       { test: /\.vue$/, loader: 'vue' } 
     ], 
     resolve: { 
      modulesDirectories: ['node_modules'] 
     } 
    }, 
    sassLoader: { 
      includePaths: [path.resolve(__dirname, "./node_modules/foundation-sites/scss/")] 
      }, 
    devServer: { 
     proxy: { 
      '/api/*': { 
       target: 'http://localhost:4567', 
       secure: false 
      } 
     } 
    } 
}; 

我可以解決這個由包括通過亭子基礎,而不是,但我想消除涼亭,只使用NPM。

+0

timaschew的回答很簡單,我http://stackoverflow.com/a/35373347/1783439 –

回答

7

我已經能夠通過webpack做到這一點,本質上是把它作爲一個模塊進行加載。

這基本上是一個黑客,但基金會確實需要更新其JS以作爲commonJS模塊加載。

該問題源於Foundation的JS以源代碼中的嵌套IFFE中的不規則方式引用依賴關係。有時jQuery是本地的jQuery參數,有時它是$,有時候是window.jQuery。這真是一個混合包。所有不同機制的組合意味着沒有單一的勻場解決方案,而只是非模塊化地加載物體。

老實說,這裏非常有業餘時間,但截至撰寫本文時,他們上週剛剛發佈了這個東西,所以希望它很快就會解決。

安美居...到弓:

我做一個單獨的供應商捆綁並加載所有的業餘小時的第三方故宮圖書館那裏,因爲我只是厭倦了所有必要的包裹的各種勻場機制的戰鬥運行良好的開源npm軟件包代碼。

我的供應商捆綁包是一個單獨的入口點,我使用webpack註冊,並且它包含所有不擅長模塊的庫。

require('!!script!jquery/dist/jquery.min.js'); 

require('!!script!uglify!foundation-sites/js/foundation.core.js'); 
require('!!script!uglify!foundation-sites/js/foundation.accordion.js'); 
require('!!script!uglify!foundation-sites/js/foundation.util.keyboard.js'); 
require('!!script!uglify!foundation-sites/js/foundation.util.motion.js'); 
// etc. 

確保已腳本裝載機安裝

npm install script-loader -D 

的!意思是「忽略我在配置中已經定義的所有其他規則」。使用腳本加載器可以告訴webpack在窗口範圍內加載和執行文件,就像在頁面中包含腳本標記一樣。 (但它並沒有,很明顯)

你可能會更喜歡並編寫自己的解析規則,以便它只檢查基礎庫中的東西,但我沒有打擾,因爲我希望庫如普遍一樣基金會在不久的將來會一起行動,所以我可以刪除這個黑客​​。

另外...在你的主要webpack配置中,你會想引用jQuery和其他以這種方式加載的全局窗口變量作爲外部參數。

var webpackConfig = { 
    entry: { // blah }, 
    output: { // blah }, 
    loaders: [ // blah ], 
    externals: { 
     jquery: "jQuery" 
    } 
}; 
+1

使用你如何提供了jQuery的基礎腳本,需要勻場? – Mihail

+1

啊,對不起,我只發佈了我的供應商包的一個片段。在我的供應商捆綁中,我採用基本相同的方式進行升級。將更新答案。 –

+2

可悲的是我得到一個'Uncaught TypeError:$(...)。基礎是不是一個函數'在瀏覽器:(。應該是一個很好的完整的例子... – slothy

2

這是我如何使用黑客。我把基礎和jQuery放在一個名爲vendor的獨立入口點,並用腳本加載器加載它們。唯一相關的位在供應商入口點。

var path = require('path'); 
var webpack = require('webpack'); 
var hotMiddlewareScript = 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000&reload=true'; 
var autoprefixer = require('autoprefixer'); 

module.exports = { 
    name: 'main', 

    devtool: 'eval', 

    entry: { 
    client: [ 
     path.resolve(__dirname, 'client', 'index.js'), 
     hotMiddlewareScript 
    ], 
    vendor: [ 
     'font-awesome/css/font-awesome.css', 
     'foundation-sites/dist/foundation-flex.css', 
     '!!script!jquery/dist/jquery.min.js', 
     '!!script!foundation-sites/dist/foundation.min.js', 
    ] 
    }, 

    output: { 
    path: path.resolve(__dirname, 'dist'), 
    filename: '[name].js', 
    publicPath: '/dist/' 
    }, 

    resolve: { 
    modulesDirectories: ['node_modules', './client'], 
    extensions: ['', '.js', '.jsx'] 
    }, 

    plugins: [ 
    new webpack.optimize.OccurenceOrderPlugin(), 
    new webpack.HotModuleReplacementPlugin(), 
    new webpack.NoErrorsPlugin(), 
    new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.bundle.js'), 
    new webpack.ProvidePlugin({'$': 'jquery', jQuery: 'jquery'}) 
    ], 

    module: { 
    loaders: [ 
     { test: /\.(js|jsx)$/, loaders: ['react-hot', 'babel-loader'], exclude: /node_modules/, include: path.resolve(__dirname, 'client') }, 
     { test: /\.scss$/, loader: "style!css!autoprefixer-loader?browsers=last 2 versions!sass" }, 
     { test: /\.css$/, loader: "style!css" }, 
     // { test: /\.(png|jpg|jpeg|gif)$/, loader: 'file-loader?name=images/[name].[ext]' }, 
     { test: /\.(webm|mp4|mov|m4v|ogg)$/, loader: 'file-loader?name=videos/[name].[ext]' }, 
     { test: /\.(eot|svg|ttf|woff|woff2)/, loader: 'file-loader?name=fonts/[name].[ext]' } 
    ] 
    } 
}; 
7

我會根據梅森Houtz並且如果藥(pharmakon)的偉大的答案後我的完整的解決方法也可以幫助別人,因爲我與它掙扎了一下,在這個過程中學習的WebPack。

在我的情況下,我有一個額外的複雜,因爲其他jQuery插件只能在自己的模塊內工作,而在他們的屬性之外是undefined。顯然他們使用的是本地重複的jQuery對象。

無論如何,這裏就是你需要做什麼:

  1. 安裝腳本裝載機:npm install --save-dev script-loader

  2. 在的WebPack的配置:

    • 添加新條目,讓我們稱之爲vendor 。每當Webpack運行時,這將編譯一個新的vendor.js

      entry: { 
          ..., 
          "vendor": [ 
           "!!script!jquery/dist/jquery.min.js", 
           "!!script!foundation-sites/dist/foundation.min.js" 
          ] 
      }, 
      
    • jquery添加到外部。這可以確保您的主JS內的任何對jquery的引用將替換爲對全局jQuery變量的引用,該變量可通過上面的vendor.js獲得。

      entry : { 
          // ... 
      }, 
      externals: { 
          jquery: "jQuery" 
      } 
      
  3. 確保使用jQuery的每一個模塊導入它:

    var $ = require('jquery'); 
    

以上externals配置將與全球jQuery變量的引用取代,而不是重新它,正確導入重複的jQuery。 (可選)您可以使用ProvidePlugin,它會在模塊中遇到jQuery時自動執行上述操作,爲您節省幾個按鍵。如果你想要的是,擺在的WebPack的配置如下:

plugins: [ 
    // ..., 
    new webpack.ProvidePlugin({ 
     '$': 'jquery', 
     jQuery: 'jquery' 
    }) 
] 
  • 包括新vendor.js到您的網頁,主要JS之前明顯。
  • 這很可能有一個更簡單或更優雅的方式來做到這一點,但我只是想要一個快速的工作解決方案,直到基金會希望儘快解決問題。

    14

    我有同樣的問題,但我不想有兩個.js文件(供應商和應用程序)!

    對於我來說,一切都需要放在一個單獨的文件,所以,我有這樣的:

    webpack.conf.js,使用的外部(也許有沒有外部的另一種方式,但對我來說,這是足夠了):

    externals: { 
        jQuery: 'jQuery', 
        foundation: 'Foundation' 
    }, 
    

    創建您的源文件夾文件(任何名稱,如/libs/foundation.js):

    // jQuery 
    var $ = require('jquery'); 
    global.jQuery = $; 
    
    // if you want all features of foundation 
    require('./node_modules_folder/foundation-sites/dist/foundation.js'); 
    
    // if you want only some features 
    // require('./node_modules/what-input/what-input'); 
    // require('./node_modules/foundation-sites/js/foundation.core'); 
    // require('./node_modules/foundation-sites/js/....'); 
    
    export default Foundation; 
    

    現在,您可以用粉底使用以下語法任何JS:

    import Foundation from './libs/foundation'; 
    
    +1

    這個解決方案很好用;) – Mik378

    +0

    是的,它確實如此。我試圖將它與反應樣板整合,這似乎已經完成了。現在到網站:) – ariestav

    4

    雖然@羅伯託的答案看起來不錯,我想提供一個簡單的解決方案(其中,它不需要任何額外的供應商/基礎文件) 。

    在你的WebPack配置使用本:

    // this will force the export of the jQuery 'foundation' function, 
    // which we'll use later on 
    loaders: [ 
        { 
        test: /(foundation\.core)/, 
        loader: 'exports?foundation=jQuery.fn.foundation' 
        } 
    ], 
    
    // this makes sure that every module can resolve define(['foundation']) calls 
    resolve: { 
        extensions: ['', '.js'], 
        alias: { 
        foundation: 'foundation-sites/js/foundation.core' 
        } 
    }, 
    
    // this makes sure 'jQuery' is available to any jQuery plugin you might want 
    // to load (including Foundation files) regardless of how they are written 
    plugins: [ 
        new webpack.ProvidePlugin({ 
        $: 'jquery', 
        jQuery: 'jquery', 
        'window.jQuery': 'jquery' 
        }) 
    ] 
    

    而在你的index.js:

    // thanks to the ProvidePlugin we don't need to 
    // > import $ from 'jquery'; 
    
    // required core foundation files 
    import { foundation } from 'foundation-sites/js/foundation.core'; 
    import 'foundation-sites/js/foundation.util.mediaQuery'; 
    
    /* import here any additional module */ 
    
    // we need to attach the function we force-exported in the config 
    // above to the jQuery object in use in this file 
    $.fn.foundation = foundation; 
    
    // ready to go 
    $(document).ready(function() { 
        $(document).foundation(); 
        … 
    }); 
    

    注#1(謝謝@mtyson)
    您需要使用出口裝載機:$ npm install --save exports-loader$ npm install --save-dev exports-loader

    注#2
    由於jQuery在單個模塊內部不是全局的(或出於某種其他原因,這是我無法理解的),因此可能存在依賴Foundation JS組件的data-屬性的問題。如果是這種情況,您可以始終使用Foundation文檔中記錄的純JavaScript方式。

    +1

    我不得不包括在我的package.json中:「exports-loader」:「^ 0.6.3」, – mtyson

    +0

    此外,要使樣式工作,必須看基礎 - 所有內容都包含在內:http://stackoverflow.com/a/35373347/467240 – mtyson

    +0

    當我試圖將這與'foundation.dropdown'一起使用時,我得到一個錯誤'Can not read property'register'of undefined'。有任何想法嗎? – jkinz

    5

    只需使用腳本加載器(npm i script-loader)並在輸入前加上script!即可。 然後它將在全球範圍內進行評估。

    要加載所有從基礎用js文件這個

    import 'script!jquery' 
    import 'script!what-input' 
    import 'script!foundation-sites' 
    

    像我這樣做,我entry point

    您可以檢查出我的樣板項目,嘗試一下:https://github.com/timaschew/r3-foundation-boilerplate

    +0

    謝謝,不得不看你的模板一段時間,以獲得樣式工作 – mtyson

    +3

    簡單,它的工作 – vumaasha

    +0

    這工作粘滯導航和vue.js一旦我添加了'外部:{foundation:'基金會'},到webpack.conf根據Roberto Correia解決方案 –

    1

    它的工作原理罰款爲webpack如果你可以告訴它忽略define測試的麻煩代碼如下:

    if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') 
        module.exports = Reveal; 
        if (typeof define === 'function') 
        define(['foundation'], function() { 
        return Reveal; 
        }); 
    

    最好的辦法是使用imports-loader並將define設置爲false。

    require('foundation-sites/js/foundation.core.js'); 
    require('foundation-sites/js/foundation.util.keyboard.js'); 
    require('foundation-sites/js/foundation.util.box.js'); 
    require('foundation-sites/js/foundation.util.triggers.js'); 
    require('foundation-sites/js/foundation.util.mediaQuery.js'); 
    require('foundation-sites/js/foundation.util.motion.js'); 
    require('imports?define=>false!foundation-sites/js/foundation.reveal.js'); 
    
    1

    如果您仔細查看基金會網站6.2。0模塊,你會發現在路徑中的變化如下

    1. 基礎的網站/距離/ CSS/foundation.min.css
    2. 基礎的網站/距離/ JS/foundation.min。 JS

    所以基本上你必須在的WebPack confing文件條目修改如下

    module.exports = { 
         entry: ['script!jquery/dist/jquery.min.js', 
         'script!foundation-sites/dist/js/foundation.min.js', 
         './app/app.jsx' 
         ] 
    } 
    

    和風格的進入應該是這樣的

    require('style!css!foundation-sites/dist/css/foundation.min.css');