Cannot import ES6 module inside React component - javascript

I have a config file named config.js that looks like this :
var config = {};
config.web = {};
config.web.param = 'oneParam';
module.exports = config;
I also use Webpack to give alias to my modules so I have this line in my webpack.config.js :
alias: {
configFile: 'app/config.js'
}
I then try to import my config file with this :
import config from 'configFile';
Inside a React Component.
However, when I try to access configvariable, all I get is an undefined error.
My full webpack.config.js
var webpack = require('webpack');
module.exports = {
entry: [
'./app/app.jsx'
],
output: {
path: __dirname,
filename: './dist/bundle.js'
},
externals: {
'Config': JSON.stringify()
},
resolve: {
root: __dirname,
alias: {
configFile: 'app/config.js'
},
extensions: ['', '.js', '.jsx']
},
module: {
loaders: [
{
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-0']
},
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/
},
{test: /\.scss?$/, exclude: /node_modules/, loader: "style-loader!css-loader!sass-loader!"},
{test: /\.css?$/, loader: "style-loader!css-loader!"},
{test: /\.(png|jpg)$/, loader: "file-loader?name=./dist/images/[name].[ext]"}
]
},
devtool: 'cheap-module-source-map'
};
What am I doing wrong here ?

Try
import * as config from 'configFile';
And try console.log the config variable and see if you get not defined. If it is still not defined, the problem lies in exporting the configFile.

Your path 'app/config.js' will the most probably point to node_modules/app/config.js.
The simplest solution will be changing your path in alias to absolute (or more proper in your scenario):
alias: {
configFile: '/app/config.js'
}

You should define relative path to root:
alias: {
configFile: './app/config.js'
}
or relative to contentBase

Related

Import a SCSS "exported" variable into the Javascript code within a .vue file that is loaded by vue-loader and bundled by webpack

I have a variable in my vars.scss that I want to access from Javascript in root/app/app.vue.
root/app/scss/vars.scss
:export {
cursor: #fff;
}
root/app/app.vue
<template>
<div id="yes">
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import colors from '#/scss/vars.scss';
export default Vue.extend({
mounted() {
console.log(colors.cursor);
},
});
</script>
<style >
</style>
I have read approximately 30 different stackoverflow questions that appear to be dealing with the similar problem of importing variables into the style block of the .vue file, as well as the identical problem of importing the variables directly into the Javascript code. As a result, my webpack.config.js looks like the following:
root/webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const env = process.env.NODE_ENV
module.exports = {
entry: './app/index.ts',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'staticfiles')
},
resolve: {
extensions: [ '.ts', '.js', '.vue', '.scss', '.sass'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'#': path.resolve(__dirname, '/app/')
}
},
plugins: [
new HtmlWebpackPlugin(),
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin(),
new VueLoaderPlugin()
],
module: {
rules: [
{
enforce: 'pre',
test: /\.(js|vue|ts)$/,
loader: 'eslint-loader',
exclude: /node_modules/
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
// Since sass-loader (weirdly) has SCSS as its default parse mode, we map
// the "scss" and "sass" values for the lang attribute to the right configs here.
// other preprocessors should work out of the box, no loader config like this necessary.
'scss': 'vue-style-loader!css-loader!sass-loader',
'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax',
}
// other vue-loader options go here
}
},
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
},
{
test: /\.tsx?$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
appendTsSuffixTo: [/\.vue$/],
}
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
},
{
test: /\.s(a|c)ss$/,
use: [ {
loader: "style-loader",
options: {
sourceMap: env === 'development',
}
}, {
loader: "css-loader",
options: {
sourceMap: env === 'development',
}
}, {
loader: "sass-loader",
options: {
sourceMap: env === 'development',
}
},
'vue-style-loader'],
}]
}
};
I have also tried, in the test: /\.s(a|c)ss$/ section, to put vue-style-loader at the beginning of the array.
I have tried many combinations of filenames when attempting to import the .scss file, such as relative (../scss/vars.scss), removing the extension, using .css as an extension, etc.
The error I get is:
ERROR in /home/Documents/application/app/app.vue.ts
[tsl] ERROR in /home/Documents/application/app/app.vue.ts(10,28)
TS2307: Cannot find module '#/scss/vars.scss'.
My question:
In a project that uses vue-style-loader and vue-loader to build .vue files with webpack, how can I import .scss variables into the <script> portion of a .vue file? (please note - I am NOT attempting to import them into the <style> section of the .vue file)
An example based on my comment:
SCSS fragment:
$foo: #333;
body {
--variable-foo: $foo;
}
And then anywhere in the JavaScript
const value = document.body.style.getPropertyValue("--variable-foo");
console.log(value); // outputs "#333"

Navigator undefined on React Typescript Firebase project

I've been googling for a couple hours now and can't seem to resolve my issue.
I have a webpack/React/Typescript/Mobx setup and am attempting to use firebase.
Here is my webpack config: (boilerplate from this repo)
var webpack = require('webpack');
var path = require('path');
// variables
var isProduction = process.argv.indexOf('-p') >= 0;
var sourcePath = path.join(__dirname, './src');
var outPath = path.join(__dirname, './dist');
// plugins
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var WebpackCleanupPlugin = require('webpack-cleanup-plugin');
module.exports = {
context: sourcePath,
entry: {
main: './main.tsx'
},
output: {
path: outPath,
filename: 'bundle.js',
chunkFilename: '[chunkhash].js',
publicPath: '/'
},
target: 'web',
resolve: {
extensions: ['.js', '.ts', '.tsx'],
// Fix webpack's default behavior to not load packages with jsnext:main module
// (jsnext:main directs not usually distributable es6 format, but es6 sources)
mainFields: ['module', 'browser', 'main'],
alias: {
app: path.resolve(__dirname, 'src/app/'),
assets: path.resolve(__dirname, 'src/assets/')
}
},
module: {
rules: [
// .ts, .tsx
{
test: /\.tsx?$/,
use: [
isProduction
? 'ts-loader'
: {
loader: 'babel-loader',
options: {
babelrc: false,
plugins: ['react-hot-loader/babel']
}
},
'ts-loader'
],
// : ['babel-loader?plugins=react-hot-loader/babel&presets=', 'ts-loader'],
exclude: /node_modules/
},
// css
{
test: /\.css$/,
exclude: /node_modules/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
query: {
modules: true,
sourceMap: !isProduction,
importLoaders: 1,
localIdentName: '[local]__[hash:base64:5]'
}
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: [
require('postcss-import')({ addDependencyTo: webpack }),
require('postcss-url')(),
require('postcss-cssnext')(),
require('postcss-reporter')(),
require('postcss-browser-reporter')({
disabled: isProduction
})
]
}
}
]
})
},
{
test: /\.css$/,
include: /node_modules/,
use: ['style-loader', 'css-loader']
},
// static assets
{ test: /\.html$/, use: 'html-loader' },
{ test: /\.(png|jpg)$/, use: 'url-loader?limit=10000' },
{ test: /\.webm$/, use: 'file-loader' }
]
},
optimization: {
splitChunks: {
name: true,
cacheGroups: {
commons: {
chunks: 'initial',
minChunks: 2
},
vendors: {
test: /[\\/]node_modules[\\/]/,
chunks: 'all',
priority: -10
}
}
},
runtimeChunk: true
},
plugins: [
new WebpackCleanupPlugin(),
new ExtractTextPlugin({
filename: 'styles.css',
disable: !isProduction
}),
new HtmlWebpackPlugin({
template: 'assets/index.html'
})
],
devServer: {
contentBase: sourcePath,
hot: true,
inline: true,
historyApiFallback: {
disableDotRule: true
},
stats: 'minimal'
},
devtool: 'cheap-module-eval-source-map',
node: {
// workaround for webpack-dev-server issue
// https://github.com/webpack/webpack-dev-server/issues/60#issuecomment-103411179
fs: 'empty',
net: 'empty'
}
};
Just by including firebase in my app i relentlessly end up with this error:
Uncaught TypeError: Cannot read property 'navigator' of undefined auth.esm.js?69b5:10
I have tested by including a simple component like so:
import * as React from 'react';
import * as Styles from './styles.css';
import 'app/utils/FirebaseUtil';
interface TestProps {}
export const Test: React.StatelessComponent<TestProps > = () => (
<div className={Styles.root}>
{'Hello World'}
</div>
);
FirebaseUtil:
import * as firebase from 'firebase';
const config = {
apiKey: '**my key here**',
authDomain: '** my domain here **'
};
firebase.initializeApp(config);
export const fbAuth = firebase.auth;
No matter what I seem to do I get the navigator error. Even if i dont export the auth object. As far as I can tell its related to babel-loader adding strict-mode according to this SO question, i think? All other related searches seem to have to do with firebase-ui, which i am not using in any way.
But I have no idea how he manages to turn off strict mode, not to mention the OP is not using typescript and I am using ts-loader in this case. I can't for the life of me figure out how to get it working. Aside from all of this if I do try use the firebase object for auth() for example I get a bunch of warnings from webpack about auth not existing on the firebase object. Totally stumped.
So in case anyone else runs into this problem. It appears it was a package version issue. Im assuming that the package versions specifically included in the boilerplate i used didn't play well with firebase.
I updated typescript, react-hot-loader, and most likely the issue webpack from version 3.0.4 to 4.12.1 and things seem to be working ok now. Also with the updates I now import firebase like so:
import firebase from '#firebase/app';
import '#firebase/auth';
Hope this helps someone.
In my case I fixed this importing functions
import firebase from 'firebase/app'
import 'firebase/functions'
import 'firebase/analytics'

Possible to have separate src from modules and webpack config?

I have an app that is in a different folder structure than the modules installed from the package.json and I cannot find a way to make it work:
Structure:
includes
build
build stuff
src
shared assets
js
...APP (the app is a few folders down still)
How can I specify that the modules are somewhere and the app is in another place? Is this even possible? as If I set up the src of my app in the place where the build setup is, everything work as expected.
Where is my very simple webpack config.
var getters = require('./../gulpfile.js/config/getters');
var path = require('path');
var appRoot = path.resolve(__dirname, '../src');
var appRoot2 = path.resolve(__dirname, '../../main/jcr_root/etc/designs/fit/includes/shared_assets/js/vueapps/chat_app/src');
module.exports = {
context: appRoot2,
entry: './main.js',
output: {
filename: 'app.js',
path: getters.js.vue.apps.chatapp.dist
},
module: {
loaders: [
{
test: /\.vue$/,
loader: 'vue-loader',
exclude: /node_modules/
},
{
test: /\.js$/,
loaders: 'babel-loader',
exclude: /node_modules/
}
]
},
resolve: {
modules: [
'node_modules'
]
}
};
I this you can see I have appRoot and appRoot2, appRoot works as expected, appRoot2 fails giving me this error.
ERROR in Entry module not found: Error: Can't resolve 'babel-loader' in ...
EDIT: Forgot to mention I'm using :
"vue-loader": "^9.4.0".
"webpack": "^2.2.0".
"babel-loader": "^6.3.2".
EDIT2: Got it working, had to specify with another option:
resolveLoader: {
modules: [
nodeRoot
],
}
Also in the loader had to add this option:
{
test: /\.js$/,
loaders: 'babel',
exclude: /node_modules/,
query: {
presets: [nodeRoot + '/babel-preset-es2015'],
}
}
With the path to the preset.

Passing getChildContext() to reactjs higher order components throws unexpected token error in webpack

I got the following example from HERE to make a higher order component for passing context reliably.
However, there is a Unexpected token error passing getChildContext() function when compiling the script using webpack:
getChildContext = () => getChildContext(this.props);
^^^
Code:
const provideContext =
(childContextTypes, getChildContext) => (Component) => {
class ContextProvider extends React.Component {
getChildContext = () => getChildContext(this.props);
render() {
return <Component {...this.props} />;
}
}
ContextProvide.childContextTypes = childContextTypes;
return ContextProvider;
};
Is there a workaround way of passing the function?
My webpack config:
var common = {
output: {path: BUILD_DIR},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
include: APP_DIR,
query: {
presets: ['es2015', 'react']
}
},
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.(png|woff|woff2|eot|ttf|svg)$/,
loader: 'url-loader?limit=100000'
},
{
test: /\.(png|jpg)$/,
loader: 'file-loader'
}
]
},
resolve: {
alias: {
'react': path.join(__dirname, 'node_modules', 'react'),
'react-dom': path.join(__dirname, 'node_modules', 'react-dom')
},
extensions: ['', '.js']
},
};
config.push(
merge(common, {
entry: {
ItemPage:APP_DIR+'/page/'+fileName+'.js',
},
devtool: 'source-map',
output: {
filename: "[name].js",
libraryTarget: 'umd',
library: "[name]"
},
externals: [{
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react',
},
"react-dom": "ReactDOM"
}]
})
);
module.exports = config;
You are getting Unexpected token because you are missing one babel plugin, transform-class-properties which is included in stage-1 preset
With stage-1, it works
Without stage-1, it does not work
So in order to fix it, you have to
1º Install stage-1
npm install --save-dev babel-preset-stage-1
2º Add it to .babelrc
{
"presets": ["react","es2015","stage-1"]
}
Or to the webpack config
query: {
presets: ["react","es2015","stage-1"]
}

webpack: 'import' not working whereas 'require' works okay

I have a strange issue using webpack.
This my webpack.config.js:
import webpack from "webpack";
import path from "path";
//not working: import ExtractTextPlugin from "extract-text-webpack-plugin";
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const GLOBALS = {
"process.env.NODE_ENV": JSON.stringify("production"),
__DEV__: false
};
export default {
debug: true,
devtool: "source-map",
noInfo: true,
entry: "./src/bootstrap",
target: "web",
output: {
path: path.join(__dirname, "dist"),
publicPath: "/",
filename: "bundle.js"
},
resolve: {
root: path.resolve(__dirname),
alias: {
"~": "src"
},
extensions: ["", ".js", ".jsx"]
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.DefinePlugin(GLOBALS),
new ExtractTextPlugin("styles.css"),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin()
],
module: {
loaders: [
{ test: /\.jsx?$/, include: path.join(__dirname, "src"), loaders: ["babel"] },
{ test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: "file" },
{ test: /\.(woff|woff2)$/, loader: "file-loader?prefix=font/&limit=5000" },
{ test: /\.ttf(\?v=\d+.\d+.\d+)?$/, loader: "file-loader?limit=10000&mimetype=application/octet-stream" },
{ test: /\.svg(\?v=\d+.\d+.\d+)?$/, loader: "file-loader?limit=10000&mimetype=image/svg+xml" },
{ test: /\.(jpe?g|png|gif)$/i, loaders: ["file"] },
{ test: /\.ico$/, loader: "file-loader?name=[name].[ext]" },
{
test: /(\.css|\.scss)$/,
loader: ExtractTextPlugin.extract("css?sourceMap!sass?sourceMap")
}
]
}
};
As you can see: I set up an alias "~" pointing to my "src" directory.
According to webpack documentation I should be able to import modules this way:
import { ServiceStub } from "~/utilities/service-stub";
HINT: File service-stub.js sits here: [__dirname]/src/utilities/service-stub.js.
However, this does not work since webpack is throwing an error ("Path not found.").
When I userequire instead of import, everything works fine:
const { ServiceStub } = require("~/utilities/service-stub");
The same issue is in webpack.config.js itself:
import webpack from "webpack";
import path from "path";
//not working: import ExtractTextPlugin from "extract-text-webpack-plugin";
const ExtractTextPlugin = require("extract-text-webpack-plugin");
Here some modules import well with import (modules webpack and path), some do not (module extract-text-webpack-plugin).
I worked through dozens of forums, but found no solution yet.
The problem is ESLint - not webpack.
When you are using aliases in webpack like this
resolve: {
root: path.resolve(__dirname),
alias: {
"~": "src"
},
extensions: ["", ".js", ".jsx"]
}
and you are importing this way
import { ServiceStub } from "~/services/service-stub";
ESLint cannot resolve the alias and reports an error.
To get it work you must tell ESLint to ignore some rule with "import/no-unresolved": 0. This seems to be okay because if an imported file is actually missing, webpack reports an error itself.

Categories