import JPlayer in React component (with webpack build process) - javascript

How do I access the jPlayer object within my React component? There are many places I may be doing something wrong, so bear with...
I am developing a Redux/React web application. Starting with the scaffolding provided by the Yeoman generator, generator-redux, I have the skeleton of my app in place. This is my first encounter with webpack, having used grunt/gulp/bower in the past (though never set those up from scratch, either).
I ran npm install jquery jplayer --save so now my package.json has
"dependencies":{ ...
"jplayer": "^2.9.2",
"jquery": "^2.1.4",
...}
and the jplayer module is in the node_modules directory of my project: so far so good. But the jPlayer docs don't make the import process terribly clear, and I'm not sufficiently familiar with the whole node/webpack/babel/etc. ecosystem to be very sure of myself.
My plan is to create a React component called Player which will live in a file called Player.js in the js/components directory. How do I import the jplayer object in this scheme? I'm doing import { jPlayer} from 'jplayer' at the head of my Player.js which does not seem like it is doing what I want it to be doing, but I'm honestly a bit at a loss of how to check properly. There is no jPlayer defined in this or the top level in the console...
My imports look like this:
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import * as PlayerActions from '../actions/PlayerActions';
import styles from '../../css/app.css';
import $ from 'jquery';
// import {jPlayer} from 'jplayer/dist/jplayer/jquery.jplayer';
import 'jplayer';
For debugging, I also added this to the Player class in Player.js
componentDidMount() {
console.log("Regulators, mount up");
console.log($('#jquery_jplayer_1'));
console.log($.jPlayer);
console.log(jPlayer)
}
which gives this output in the Chrome console:
Regulators, mount up
[div#jquery_jplayer_1, context: document, selector: "#jquery_jplayer_1"]
undefined
Uncaught ReferenceError: jPlayer is not defined
At this point, I would expect that $.jPlayer to be <jPlayer object> or some such. I want to call $('#jquery_jplayer_1').jPlayer(...) at this point, as per the docs for jPlayer.
I know I'm kind of stumbling about blindly here, with a partial knowledge of many components combining into a lot of confusion! Any guidance, and in particular a high-level view of these pieces and their interactions would be most welcome!
In case it's relevant, here's the webpack.config.js
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var devFlagPlugin = new webpack.DefinePlugin({
__DEV__: JSON.stringify(JSON.parse(process.env.DEBUG || 'false'))
});
module.exports = {
entry: [
'webpack-dev-server/client?http://localhost:3001',
'webpack/hot/only-dev-server',
'./js/index.js'
],
output: {
path: __dirname + '/static/',
publicPath: '/static/',
filename: 'bundle.js',
hot: true
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
devFlagPlugin,
new ExtractTextPlugin('app.css')
],
module: {
loaders: [
{ test: /\.js$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
{ test: /\.css$/, loader: ExtractTextPlugin.extract('css-loader?module!cssnext-loader') }
]
},
resolve: {
extensions: ['', '.js', '.json']
}
};

Related

How to make React show errors

Im facing an issue with React (16.13.0), tt's not showing any usable errors, instead I get this:
Uncaught Error: Minified React error #321; visit https://reactjs.org/docs/error-decoder.html?invariant=321 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
Accoording to the message I should use the debug build to see the error, however I already am (AFAIK). React dev-tools seems to agree with me:
This page is using the development build of React. 🚧
I'm using webpack#4.42.0 with mode set to development. I also use #babel/preset-env#7.8.7 and #babel/preset-react#7.8.3
webpack.config.js
const argv = require('yargs').argv;
const paths = require('./build/paths');
const jsName = `${paths.package.name}-js`;
/**
* Webpack configuration
* Run using "webpack" or "gulp js"
*/
module.exports = {
// Path to the js entry point (source).
entry: {
[jsName]: __dirname + '/' + paths.jsEntry,
},
// Path to the bundles.
output: {
path: __dirname + '/' + paths.jsDir, // directory
filename: '[name].js', // file
chunkFilename: '[name].bundle.js',
publicPath: '/static/bundles/',
},
// Use --production to optimize output.
mode: 'development',
module: {
rules: [
// JavaScript
{
test: /.js?$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
]
},
};
.babelrc
{
"presets": [
"#babel/preset-env",
"#babel/preset-react"
]
}
Ok so this is kind of embarrassing. The problem was that my errored component had a a (IDE generated) import to a the production build of React causing this behavior:
import {useContext} from 'react/cjs/react.production.min';
Should of course be:
import React, {useContext} from 'react';

error with webpack - You may need an appropriate loader to handle this file type

I am learning react and trying to create a boilerplate with webpack. I followed a tutorial by traversy everything in his video works but on my computer, I get the error message that an appropriate loader is needed to handle a particular file type.
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.export = {
entry: './src/index.js',
output: {
path: path.join(__dirname, '/dist'),
filename: 'index_bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
}
And this is the file where the error is coming from
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
ReactDOM.render(<App />, document.getElementById('app'));
Here is the error message:
ERROR in ./src/index.js 5:16 Module parse failed: Unexpected token
(5:16) You may need an appropriate loader to handle this file type. |
import App from './components/App'; |
ReactDOM.render(, document.getElementById('app')); # multi (webpack)-dev-server/client?http://localhost:8080
(webpack)/hot/dev-server.js ./src main[2]
Before you're able to use JSX syntax, you need to have a list of presets in a .babelrc file, in the root folder of your application.
Here's an example
{
"presets": [
"flow",
"es2015",
"react"
]
}
In this example babel would account for a JSX React app, with ES2015 references and flow static typing syntax.
Take a look at this link for more information.

Component not loading in Angular 2 app AoT compilation

I followed the steps on the website 'https://angular.io/guide/aot-compiler' to adapt an Angular 2 app to use AoT compilation and everything seemed to work as expected until the rollup step, which in theory cleans up the code of unused components.
Leaving the 'rollup-config.js' file the same as in the instructions, when I run 'node_modules/.bin/rollup -c rollup-config.js' I get the following error:
[!] Error: 'ToastModule' is not exported by node_modules/ng2-toastr/ng2-toastr.js
I've googled it, and I came across a solution that pointed to add a 'namedExports' field to the 'commonjs' parameter. The resulting 'rollup-config.js' is:
import nodeResolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import uglify from 'rollup-plugin-uglify';
export default {
entry: 'src/main.js',
dest: 'src/build.js',
sourceMap: false,
format: 'iife',
onwarn: function(warning) {
if(warning.code === 'THIS_IS_UNDEFINED') { return; }
console.warn(warning.message);
},
plugins: [
nodeResolve({jsnext: true, module: true}),
commonjs({
include: 'node_modules/**',
namedExports: {
'node_modules/ng2-toastr/ng2-toastr': [ 'ToastModule' ]
}
}),
uglify()
]
}
Now, the script generates the 'build.js' file and I can load it through the index.html file, but the component 'ng2-toastr' is not working (the component shows a 'toast' like message, appearing on one side of the screen and disappearing after a few seconds).
Did I miss something? Thanks in advance,

Webpack exclude entries for CommonsChunkPlugin

I am trying to set up webpack production configuration. All looks well. However, I realized that while using the commons chunk plugin, it covers all the files in common as expected. What I want to do is, separation of common library modules and common application modules. My config file is :
module.exports = {
entry: {
lib: ["react", "react-dom"],
app: "./ui-v2/app/app.js",
app2: "./ui-v2/app/app2.js"
},
output: {
path: path.join(__dirname, "target/ui/v2"),
filename: "/app/[name].[chunkhash].min.js"
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.(png|jpg|svg)/,
loader: "file-loader?name=img/[name].[hash].[ext]"
// loaders: ["url", "image-webpack"]
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!autoprefixer-loader!sass-loader", {
publicPath: __dirname
})
},
{
test: /\.(woff|woff2|ttf|eot)$/,
loader: "file-loader?name=fonts/[name].[hash].[ext]"
}
]
},
plugins: [
clean,
new webpack.optimize.CommonsChunkPlugin("common", "app/common.[chunkhash].js"),
new webpack.ProvidePlugin({
React: "react",
ReactDOM: "react-dom",
$: "jquery",
_: "lodash"
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
sourceMap: true
},
mangle: {
except: ["exports", "import", "$", "_", "require", "React", "ReactDOM"]
}
}),
new ExtractTextPlugin("styles/[name].[contenthash].css"),
new Manifest()
]
}
Basically I have 3 modules in the app; app.js, app2.js and a common component user.js.
What I want to achieve is to bundle all library related files like react, react-dom, lodash, etc in a lib bundle, and common application components like user.js in a common bundle. In order to do this, I thought there might be an option to exclude the files that I don't want them to go to "common" file. If I use this output, what is the point for long term caching files for library bundles because whenever I get a common component in my project, they will go into the common bundle and the content hash will be different, but nothing changes in this library files like react, jquery, lodash, etc.
Anyway, what I have at the end of build process is everything still goes into the common bundle and lib has nothing and the file sizes are :
app.<hash>.min.js -> 3.05KB
app2.<hash>.min.js -> 3.05KB
lib.<hash>.min.js -> 165 Bytes (has almost nothing!)
common.<hash>.js -> 678 KB
Is there any way to achieve what I want or what would be the best approach to a production build in similar cases? Thank you!
Its because the first parameter for CommonsChunkPlugin is "common" where it should be "lib". The plugin picks up the entry with a name matching with the value of its first parameter.
A simple example config picked from webpack's wiki -
var webpack = require("webpack");
module.exports = {
entry: {
app: "./app.js",
vendor: ["jquery", "underscore", ...],
},
output: {
filename: "bundle.js"
},
plugins: [
new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"vendor", /* filename= */"vendor.bundle.js")
]
};
Note that the "vendor" entry is again specified in CommonsChunkPlugin
You should check out Webpack's DLL Plugin.
https://github.com/webpack/webpack/blob/cb3d8e2097503c7245c5dda5b7a6e9d63421a72b/examples/dll/README.md
With this plugin you bundle up common 3rd party vendor dependencies such as React and friends in a DLL, which is essentially just a JSON Manifest that goes along with your requires wrapped in webpack context and cached to disk.
In your project code, you would have your shared components which depend on React and friends, and you would have your application code which depend on your shared components as well as react and friends.
Your project would incorporate the DLL Reference plugin as you can see here:
https://github.com/webpack/webpack/blob/cb3d8e2097503c7245c5dda5b7a6e9d63421a72b/examples/dll-user/README.md
This will see to it that your shared components and your application code pull React and other 3rd party modules from the same DLL bundle. This can help improve build times and the performance of the dev server and hot module reloading.

React is expected to be globally available

I'm playing with React (#13.3) with babel and webpack.
I have a component that's defined like this:
import BaseComponent from './BaseComponent';
export default class SomeComponent extends BaseComponent {
render() {
return (
<div>
<img src="http://placekitten.com/g/900/600"/>
</div>
);
}
}
But I get the following error:
Uncaught ReferenceError: React is not defined
I understand the error: the JSX bit is compiled into React.createElement(...) but React isn't in the current scope since it's not imported.
My questions is:
What's the clean way to work around this issue? Do I have to somehow expose React globally with webpack?
Solution used:
I followed #salehen-rahman suggestion.
In my webpack.config.js:
module: {
loaders: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'react-hot!babel?plugins[]=react-require'
}, {
test: /\.css$/,
loader: 'style!css!autoprefixer?browsers=last 2 versions'
}]
},
I also needed to fix my tests, so I added this to the file helper.js:
require('babel-core/register')({
ignore: /node_modules/,
plugins: ['react-require'],
extensions: ['.js']
});
My tests are then launched with the following command:
mocha --require ./test/helper.js 'test/**/*.js'
My questions is : What's the clean way to work around this issue ? Do I have to somehow expose React globally with webpack ?
Add babel-plugin-react-require to your project, and then amend your webpack's Babel config to have settings akin to:
loaders: [
{
test: /.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
stage: 0,
optional: ['runtime'],
plugins: [
'react-require' // <-- THIS IS YOUR AMENDMENT
]
},
}
]
Now, once you've applied the configuration update, you can initialize React components without manually importing React.
React.render(
<div>Yippee! No <code>import React</code>!</div>,
document.body // <-- Only for demonstration! Do not use document.body!
);
Bear in mind though, babel-plugin-react-require transforms your code to automatically include React imports only in the presence of JSX tag in a specific file, for a specific file. For every other file that don't use JSX, but needs React for whatever reason, you will have to manually import React.
If you have react in your node modules directory you can add import React from 'react'; at the top of your file.
You can use Webpack's ProvidePlugin. To use, update the plugins section in your Webpack config to include the following:
plugins: [
new webpack.ProvidePlugin({
'React': 'react'
})
]
This, however, doesn't solve it for the tests..

Categories

Resources