Webpack & Bower: Multiple css & js files

冷暖自知 提交于 2020-01-02 09:56:34

问题


I'm just getting started with Webpack (for use w/ React), and I'm running into an issues when trying to pull in bower packages. I have installed pickadate through bower and I have the following webpack config (original). Looking at the pickadate bower.json file, it has an array instead of just a string for main as it needs to pull in multiple js and css files.

// ./webpack/dev.config.js
// ...
resolve: {
  modulesDirectories: [
    'src',
    'node_modules',
    'bower_components'
  ],
  plugins: [
    new webpack.ResolverPlugin(
      new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
    )
  ],
  extensions: ['', '.json', '.js']
},

My Component:

import React, {Component, PropTypes} from 'react';

import $ from 'jquery';
import pickadate from 'pickadate';

class DateInput extends Component {
  // ...
}

I get the following errors for jquery and pickadate modules:

@ ./src/components/forms/DateInput.js 17:14-31
[0] ./src/components/forms/DateInput.js
[0] Module not found: Error: Cannot resolve module 'jquery' in /Users/chris7519/Desktop/react-redux-universal-hot-example/src/components/forms
[0] resolve module jquery in /Users/chris7519/Desktop/react-redux-universal-hot-example/src/components/forms
[0]   looking for modules in /Users/chris7519/Desktop/react-redux-universal-hot-example/src
[0]     /Users/chris7519/Desktop/react-redux-universal-hot-example/src/jquery doesn't exist (module as directory)
[0]     resolve 'file' jquery in /Users/chris7519/Desktop/react-redux-universal-hot-example/src
[0]       resolve file
[0]         /Users/chris7519/Desktop/react-redux-universal-hot-example/src/jquery doesn't exist
[0]         /Users/chris7519/Desktop/react-redux-universal-hot-example/src/jquery.json doesn't exist
[0]         /Users/chris7519/Desktop/react-redux-universal-hot-example/src/jquery.js doesn't exist

// ...

Module not found: Error: Cannot resolve module 'pickadate' in /Users/chris7519/Desktop/react-redux-universal-hot-example/src/components/forms
[0] resolve module pickadate in /Users/chris7519/Desktop/react-redux-universal-hot-example/src/components/forms
[0]   looking for modules in /Users/chris7519/Desktop/react-redux-universal-hot-example/src
[0]     /Users/chris7519/Desktop/react-redux-universal-hot-example/src/pickadate doesn't exist (module as directory)
[0]     resolve 'file' pickadate in /Users/chris7519/Desktop/react-redux-universal-hot-example/src
[0]       resolve file
[0]         /Users/chris7519/Desktop/react-redux-universal-hot-example/src/pickadate doesn't exist
[0]         /Users/chris7519/Desktop/react-redux-universal-hot-example/src/pickadate.json doesn't exist
[0]         /Users/chris7519/Desktop/react-redux-universal-hot-example/src/pickadate.js doesn't exist

I attempted to install both jquery and pickadate through npm, but I still get the error Cannot find module 'pickadate'


回答1:


The pickadate module on npm has a broken package.json file: it doesn't specify a main entry, so webpack has no idea how to resolve require('pickadate'). You should probably file an issue upstream for them to fix this, but in the meanwhile you can fix it in your webpack.config.js.

So, you want to install both pickadate and jquery through npm, and then add the following to webpack.config.js:

{
    resolve: {
        alias: {
            'pickadate' : 'pickadate/lib/picker',
        },
    },
 }

This basically treats all instances of require('pickadate') into require('pickadate/lib/picker'). This reaches into the pickadate package and actually requires a real file. If upstream fixes their package.json to have a main entry, you can delete this alias from your config and all your requires will work properly.

More information about how the alias option works: http://webpack.github.io/docs/configuration.html#resolve-alias




回答2:


The webpack.ResolverPlugin.DirectoryDescriptionFilePlugin doesn't handle bower.json description file when the 'main' field is an array, for example Bootstrap:

"main": [
"less/bootstrap.less",
"dist/js/bootstrap.js"
]

In that case, you should install the package using npm, and require() css files explicitly




回答3:


I faced the same issue using a pickadate wrapper (ng-pickadate), hopefully most of the quirks will apply:

  • Referencing the js files, pickadate package json entry point seems not to be ok.
  • Disabling AMD for the pickadate node modules path.
  • Add providepluing ($, Jquery, window.jquery).

Bellow the step by step guide (remove the angular part, if you just want to configure pickadate).

Following the steps mentioned in this thread, I manage to make it work without having to tweak the code under node_modules. Just a quick recap (angular 1, webpack 2 solution):

First install ng-pickadate

npm install ng-pickadate

It will download as well jquery and pickadate dependencies.

Then we need to add the depencies in our webpack.config, here there's a catch pickadate.js package json main seems not to be pointing to the right entry point, we have to manually indicate which files we want to include:

diff module.exports = { context: path.join(basePath, 'src'), resolve: { extensions: ['.js', '.ts'] }, entry: { app: './app/app.ts', vendor: [ + 'jquery', + 'angular',
+ 'pickadate/lib/picker', + 'pickadate/lib/picker.date',
+ 'ng-pickadate', ],

Now comes fun part, pickadate will try to load AMD modules, in my case we need commonjs, we don't want to change the code on the library, rather disable this using a rule (loader), just only for the pickadate folder:

diff module: { rules: [ + { + test: /pickadate/, + parser: { amd: false } + },
{ test: /\.ts$/,

Now let's review our provide plugin and ensure we have all this ways of global referencing jquery (window.jquery quite important !)

diff plugins: [ + new webpack.ProvidePlugin({ + "$": "jquery", + "jQuery": "jquery", + "window.jQuery": "jquery",
}),
It's time to start using this in our app, let's include it in the angular module where we are using it (we are using angular 1.6):

```diff import * as angular from 'angular'; import { LoginComponent } from './login.component';

export const LoginModule = angular.module('loginModule', + ['pickadate']) .component('login', LoginComponent) ; ```

And let's use the directive in the HTML (input)

diff <div class="form-group"> <label for="txtEmail">Birthdate</label> <input type="text" + pick-a-date="vm.curDate"/> </div>

All this steps are just a recap of feedback got from several issues that were open, thanks to all the chaps that were providing the right tips :-). The parts that are new are marked with "+" (it seems stackoverflow doesn't support diff).



来源:https://stackoverflow.com/questions/31863079/webpack-bower-multiple-css-js-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!