zurb framework descargar npm zurb-foundation webpack

npm - framework - zurb foundation components



NPM+Zurb Foundation+WebPack: no se puede resolver el módulo ''foundation'' (9)

Estoy trabajando en el uso de Zurb Foundation con WebPack y NPM, sin Bower.

El problema que estoy encontrando es el mismo a continuación:

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

Esencialmente, al instalar los sitios de base mediante NPM, hay referencias a un módulo "base" que no se encuentra. El error:

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

Aquí está el 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" } }

Y aquí está 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 } } } };

Puedo evitar esto al incluir la fundación a través de Bower, pero quiero eliminar Bower y usar solo NPM.


Aquí es cómo estoy usando el truco. Puse la base y el jQuery en un punto de entrada separado llamado proveedor y los cargué con el cargador de scripts. Los únicos bits relevantes están en el punto de entrada del proveedor.

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]'' } ] } };


Funciona bien para el paquete web si puede decirle que ignore la prueba de define para el código problemático a continuación:

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

La mejor manera de hacerlo es utilizar el imports-loader y establecer define en falso.

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'');


Para mí, utilicé esta solución:

Estoy usando el framework Laravel, así que primero agregué el .webpackConfig (...) al archivo webpack.mix.js :

mix.js(''resources/assets/js/app.js'', ''public/js'') .sass(''resources/assets/sass/app.scss'', ''public/css'') // By default, files from the directory "/node_modules" are not processed by the Babel loader, // so in the Webpack configuration, // an exception was added for loading from the directory "/node_modules/foundation-sites/js". .webpackConfig({ module: { rules: [{ // Section "// Babel Compilation." from "/node_modules/laravel-mix/src/builder/webpack-rules.js" test: //.jsx?$/, // Thanks for the help with "exclude": http://qaru.site/questions/97960/import-a-module-from-nodemodules-with-babel-but-failed/624982#624982 exclude(file) { if (file.startsWith(__dirname + ''/node_modules/foundation-sites/js'')) { return false; } return file.startsWith(__dirname + ''/node_modules''); }, use: [ { loader: ''babel-loader'', options: Config.babel() } ] }] } });

Nota: para instalar Foundation utilicé el paquete https://github.com/laravel-frontend-presets/zurb-foundation . Y agregó el código para cargar Foundation en el archivo /resources/assets/js/bootstrap.js :

/** * We''ll load jQuery and the Foundation jQuery plugin which provides support * for JavaScript based Foundation features such as modals and tabs. This * code may be modified to fit the specific needs of your application. */ try { window.$ = window.jQuery = require(''jquery''); require(''foundation-sites/dist/js/foundation''); // ''foundation.min'' can also be used if you like // The app plugins for the Foundation require(''./plugins/entries/foundation''); } catch (e) {}

En segundo lugar , creé el archivo /resources/assets/js/plugins/entries/foundation.js (el archivo se incluye en el código de arriba // The app plugins for the Foundation. ). En el cual incluí mis módulos (ejemplo):

import { CropText } from ''../cropText''; Foundation.plugin(CropText, ''CropText'');

Tercero , creé dos archivos para incluir los complementos de Foundation :

1) /resources/assets/js/plugins/foundation.plugin.js

// By default, files from the directory "/node_modules" are not processed by the Babel loader, // so in the Webpack configuration, // an exception was added for loading from the directory "/node_modules/foundation-sites/js". import { Plugin } from ''foundation-sites/js/foundation.plugin''; export {Plugin};

2) /resources/assets/js/plugins/foundation.util.mediaQuery.js

// By default, files from the directory "/node_modules" are not processed by the Babel loader, // so in the Webpack configuration, // an exception was added for loading from the directory "/node_modules/foundation-sites/js". import { MediaQuery } from ''foundation-sites/js/foundation.util.mediaQuery''; export {MediaQuery};

En el cuarto , creé un archivo para mi complemento usando la plantilla de complementos de Foundation , que incluye 2 de los archivos anteriores:

/resources/assets/js/plugins/cropText.js

''use strict''; import $ from ''jquery''; import { MediaQuery } from ''./foundation.util.mediaQuery''; import { Plugin } from ''./foundation.plugin''; /** * CropText plugin. * @plugin app.cropText */ class CropText extends Plugin { /** * Creates a new instance of CropText. * @class * @name CropText * @fires CropText#init * @param {Object} element - jQuery object to add the trigger to. * @param {Object} options - Overrides to the default plugin settings. */ _setup(element, options = {}) { this.$element = element; this.options = $.extend(true, {}, CropText.defaults, this.$element.data(), options); this.className = ''CropText''; // ie9 back compat this._init(); } /** * Initializes the CropText plugin. * @private */ _init() { MediaQuery._init(); this.cropText(); } /** * Crops the text. */ cropText() { var size = +this.options.cropSize; $(this.$element).each(function(i, value) { var $valueText = $(value).text(), $valueHtml = $(value).html(); if($valueText.length > size){ $(value).html(''<span>'' + $valueText.slice(0, size).trim() + ''</span>'' + ''...'').wrapInner(''<a></a>''); var revealId = ''#'' + $(value).attr(''data-open''); if ($(revealId + '' .close-button'').attr(''data-close'') != undefined) { $(revealId + '' .close-button'').before($valueHtml); } else { $(revealId).append($valueHtml); } new Foundation.Reveal($(revealId), { ''data-overlay'' : false }); } else { $(value).removeAttr(''data-open'').removeAttr(''tabindex''); } }); } } /** * Default settings for plugin */ CropText.defaults = { /** * The size of the cropped text. * @option * @type {number} * @default 255 */ cropSize: 255 }; export {CropText};

Es todo A continuación, solo necesito incluir un archivo JavaScript estándar en el código HTML de la página e inicializar la Fundación (ejemplo):

/resources/views/layouts/app.blade.php

<script src=" {{ mix(''/js/app.js'') }} "></script> <script> $(document).foundation(); </script>

PD Perdón por mi inglés ;-), utilicé Google Translate.


Publicaré mi solución completa basada en las excelentes respuestas de Mason Houtz y pharmakon en caso de que ayude a alguien, ya que luché con eso un poco, aprendiendo Webpack en el proceso.

En mi caso tuve una complicación adicional, porque otros complementos de jQuery funcionaban de alguna manera solo dentro de su propio módulo, mientras que fuera de sus propiedades undefined estaban undefined . Aparentemente, estaban usando un objeto jQuery local, duplicado.

De todos modos, esto es lo que debes hacer:

  1. Instale scripts-loader: npm install --save-dev script-loader

  2. En la configuración de Webpack:

    • Añadir nueva entrada, llamémoslo vendor . Esto compilará un nuevo vendor.js cada vez que se ejecute Webpack.

      entry: { ..., "vendor": [ "!!script!jquery/dist/jquery.min.js", "!!script!foundation-sites/dist/foundation.min.js" ] },

    • Añadir jquery a los externos. Esto asegura que cualquier referencia a jquery dentro de su JS principal será reemplazada por una referencia a la variable jQuery global, que está disponible por vendor.js arriba.

      entry : { // ... }, externals: { jquery: "jQuery" }

  3. Asegúrate de que cada módulo que usa jQuery lo importe:

    var $ = require(''jquery'');

La configuración externals anterior lo reemplazará con una referencia a la variable jQuery global, en lugar de volver a importar jQuery duplicados "correctamente". Opcionalmente, puede utilizar ProvPlugin, que automáticamente hará lo anterior cada vez que encuentre jQuery en un módulo, lo que le ahorrará algunas pulsaciones de teclas. Si quieres eso, pon lo siguiente en la configuración de Webpack:

plugins: [ // ..., new webpack.ProvidePlugin({ ''$'': ''jquery'', jQuery: ''jquery'' }) ]

  1. Incluya el nuevo vendor.js en su página, obviamente antes del JS principal.

Es muy posible que haya una forma más fácil o más elegante de hacer esto, pero solo quería una solución rápida y operativa, hasta que la Fundación, con suerte, solucione el problema pronto.


Pude hacer esto con el paquete web haciendo básicamente una ejecución final alrededor de cargarlo como un módulo.

Sin embargo, esto es básicamente un truco, Foundation realmente necesita actualizar su JS para poder cargarse como un módulo común de JS.

El problema se deriva de las dependencias de referencia JS de Foundation de manera errática dentro de las IFFE anidadas en el código fuente. A veces jQuery es el parámetro local de jQuery, a veces es $, a veces es window.jQuery. Es realmente una bolsa mixta. La combinación de todos los diferentes mecanismos significa que no existe una única solución de protección que no sea simplemente cargar la cosa de forma no modular.

Sinceramente, es una hora bastante amateur, pero a partir de este escrito, lanzaron la cosa la semana pasada, así que espero que se solucione pronto.

Anyhoo ... al hack:

Hago un paquete de proveedores por separado y cargo todas las bibliotecas de npm de terceros de hora amateur allí porque simplemente me canso de luchar con todos los diversos mecanismos de ajuste necesarios para envolver el código de paquete de npm de código abierto mal enviado.

Mi paquete de proveedores es un punto de entrada separado que registro en webpack y contiene todas las bibliotecas que no funcionan bien como módulos.

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.

Asegúrese de tener instalado el cargador de scripts

npm install script-loader -D

Los !! significa "Ignorar todas las otras reglas que ya definí en la configuración". El uso del cargador de secuencias de comandos le dice a webpack que cargue y ejecute el archivo en el alcance de la ventana esencialmente igual que si hubiera incluido una etiqueta de secuencia de comandos en su página. (Pero no es así, obviamente).

Podría ser más sofisticado y escribir sus propias reglas de resolución para que solo compruebe las cosas en la biblioteca de la fundación, pero no me molesté porque espero que una biblioteca tan generalizada como Foundation actúe en conjunto en un futuro próximo, así que simplemente puedo eliminar este hack

Además ... en la configuración de su paquete web principal, querrá hacer referencia a jQuery y cualquier otra variable de ventana global cargada de esta manera como elementos externos.

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


Si bien la respuesta de @ roberto se ve muy bien, quería proporcionar una solución más simple (en la que no requiera ningún proveedor / archivo de base adicional).

En tu webpack config usa esto:

// 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'' }) ]

Y en tu 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(); … });

NOTA # 1 (gracias @mtyson)
$ npm install --save exports-loader usar el cargador de exportaciones: $ npm install --save exports-loader o $ npm install --save-dev exports-loader

NOTA 2
Dado que jQuery no es global dentro de módulos individuales (o por alguna otra razón que está más allá de mi comprensión), puede haber problemas al confiar en los atributos de data- para los componentes de Foundation JS. Si ese es el caso, siempre puede utilizar el modo javascript puro como se documenta en los documentos de Foundation.


Si ve con cuidado los módulos de Foundation-sites 6.2.0 , encontrará los cambios en la ruta de la siguiente manera

  1. foundation-sites / dist / css / foundation.min.css
  2. foundation-sites / dist / js / foundation.min.js

Básicamente, tiene que hacer cambios en el paquete web de confingir la entrada de archivos como sigue

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

y la entrada para el estilo debe ser así

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


Simplemente use el cargador de secuencias de comandos ( npm i script-loader ) y prefije sus importaciones con una script! . Luego será evaluado en el ámbito global.

Para cargar todos los archivos js desde la fundación usa este

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

Como lo hago en mi punto de entrada.

Puedes ver mi proyecto de repetición para probarlo: https://github.com/timaschew/r3-foundation-boilerplate


Tengo el mismo problema, pero no quiero tener dos archivos .js (proveedor y aplicación).

Para mí, todo tiene que estar en un solo archivo, así que hago esto:

En webpack.conf.js , use externos (quizás tenga otra forma sin externa, pero para mí, esto es suficiente):

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

cree un archivo en su carpeta de origen (cualquier nombre, como /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;

ahora, puedes usar Foundation en cualquier js usando la siguiente sintaxis:

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