erikras / react-redux-universal-hot-example

A starter boilerplate for a universal webapp using express, react, redux, webpack, and react-transform
MIT License
11.99k stars 2.5k forks source link

How do we successfully add CSS and Javascript file from 3rd Party CSS Framework into this Project? #596

Open sunkant opened 8 years ago

sunkant commented 8 years ago

I am relatively new to webpack, so this question may seem newbie..

According to the earlier issue (https://github.com/erikras/react-redux-universal-hot-example/issues/171), and also as I have checked, I can add the css from other front framework ( for example, materialize.css (http://materializecss.com/about.html), or bootstrap.css ) and make it work. I do:

import 'materialize/css/materialize.css';    (in the Client.js)

in the Client.js, with a line " { test: /.css$/, loader: "style-loader!css-loader" }, " added in the loader configuration, and it works out good.

However, when I do as above to include the jquery.js, and materialize.js / bootstrap.js as:

import 'materialize/js/jquery-2.1.1.min.js';    (in the Client.js)
import 'materialize/js/materialize.js';     (in the Client.js)

I get a ton of errors like:

Cannot resolve module 'jquery' ... Cannot resolve module 'hammerjs' ...

So anyone could tell me what should I do if I want to use 3rd party framework like Materialize ?

Thank you a lot!

hank7444 commented 8 years ago

@likeqi, are your Materialize module installed from NPM?

If so, plz try use materialize-css, Because materialize is another NPM module, link

plz try as follows:

import 'materialize-css/js/jquery-2.1.1.min.js';    (in the Client.js)
import 'materialize-css/js/materialize.js';
sunkant commented 8 years ago

Yes..actually I hand-copies the css and js file into node_modules folder.

And now I import from materialize-css, but still with errors.

Have you successfully used the bootstrap js?

hank7444 commented 8 years ago

@lukeqi could you let me see your webpack config, and your Client.js ?

sunkant commented 8 years ago

I have a notion I do not know if it is right, that we cannot "import / require" materialize.js, jquery.js in the client.js (webpack entry file), because they are not CommonJS modules. But I wonder what is the good way to put external js into this app.

sunkant commented 8 years ago

It is like:

import makeRouteHooksSafe from './helpers/makeRouteHooksSafe';

import 'materialize-css/bin/materialize.css';
import 'materialize-css/js/jquery.js';  ( I put it there myself )
import 'materialize-css/bin/materialize.js';

const client = new ApiClient();

I do not alter other things. It seems the jquery loading is wrong, the "materialize.js" cannot use jquery.

trueter commented 8 years ago

You need to require() these files, and let webpack know how to deal with .css files in dev.config.js.

hank7444 commented 8 years ago

@lukeqi http://stackoverflow.com/questions/30133526/using-materializecss-with-webpack-cannot-resolve-module-hammerjs

hank7444 commented 8 years ago

https://github.com/Dogfalo/materialize/issues/1823

sunkant commented 8 years ago

I solved it, Thank you very mcuh!@hank7444 @trueter

I generally did as https://github.com/Dogfalo/materialize/issues/1823 suggests (as scourgetheone commented on 31 Jul in the issue).

The css and js for 3rd party framework now works as normal.

I will present my partial code in this issue in short.

hank7444 commented 8 years ago

@lukeqi You are welcome, otherwise, could you provide your solution - partial code of client.js & webpack config to help other people who have the same problem also?

hank7444 commented 8 years ago

@lukeqi http://stackoverflow.com/questions/23305599/webpack-provideplugin-vs-externals

That has two ways to inject 3-party plugin, I prefer webpack.ProvidePlugin if the modules from my npm module:)

sunkant commented 8 years ago

Currently, I am doing this:

1), In dev.config.js (webpack config):

add loader:

{ test: /\.css$/, loader: "style-loader!css-loader" },

Explanation: why we add this one? To let the webpack to require the CSS file in this project.

2), In client.js:

(npm install materialize-css first and npm install jquery if not installed)

require('materialize-css/dist/css/materialize.css');
window.jQuery = require('jquery');
window.$ = require('jquery');
require('materialize-css/dist/js/materialize.js');
require('materialize-css/js/init.js');

Explanation: why we add these ones? To expose JQuery in the Browser as we normally do this by including the "http:// ... ... jquery.js" in the index.html. Then, we require the "CSS files", "Javascript files", ( note that here we require from the node_modules folder, and this load does not use "babel", as we config in the Webpack.config.js).

Now the Materialize framework ( or any other 3rd party front-end CSS framework (with js) ) would work.

This solution is hinted by https://github.com/Dogfalo/materialize/issues/1823, helped by @hank7444 @trueter

This is the solution I figure out. Please provide better solutions if possible.

gabrielmadruga commented 8 years ago

As @hank7444 said, you should avoid this:

window.jQuery = require('jquery');
window.$ = require('jquery');

With:

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

In your webpack.config.js

sunkant commented 8 years ago

Got it, great @gabrielmadruga

NotBrianZach commented 8 years ago

Is there a way to serve up this third party css or js to only a specific route or component? It seems like requiring in client.js means they will be loaded on all the pages, that is when the app first loads.

trueter commented 8 years ago

Check out code splitting as in the huge-app example of react-router and use a component scoped require to load jQuery. Or, even better, find a solution that works without jQuery ;)

NotBrianZach commented 8 years ago

this is probably inefficient in terms of number of requests that have to exchange between client and server, but I was also able to get this to work by downloading the files I wanted to include, serving as static files with express then including a script tag in the component jsx. Thanks for the tip though, that seems much more production ready.

lucasdeassis commented 6 years ago

Thanks for the approach on index.js @Lucas-Qi !!!