Webpack 4 - Module parse failed: Unexpected character '#' - javascript

I recently upgraded from Webpack 3 to 4. It's now throwing an error:
Module parse failed: Unexpected character '#' You may need an
appropriate loader to handle this file type. | #import
'./scss/variables.scss'; | | * { # ./src/index.js 1:0-22
In my styles.scss file, I am doing the following:
#import 'scss/variables.scss';
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, Helvetica, sans-serif;
}
In my index.js file, I am only doing the following:
import './style.scss';
In my webpack.dev.js, all I changed was an addition of mode: 'development':
const StyleLintPlugin = require('stylelint-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const Dotenv = require('dotenv-webpack');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'public/bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: ['babel-loader', 'eslint-loader']
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract(['css-loader', 'sass-loader'])
}
]
},
plugins: [
new StyleLintPlugin({
configFile: '.stylelintrc',
context: 'src',
files: '**/*.scss',
failOnError: false,
quiet: false,
syntax: 'scss'
}),
new ExtractTextPlugin('public/style.css'),
new Dotenv()
]
};
I don't know what change from Webpack 3 to 4 has caused this error.
The issue I'm having is very similar to the issue posted here: Webpack 4 Module parse failed: Unexpected character '#' (1:0)
I have been through all related stackoverflow questions and none of them helped.
Here are the relevant dependencies in my package.json:
"babel-loader": "^7.1.4",
"css-loader": "^0.28.11",
"eslint-loader": "^1.9.0",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"node-sass": "^4.9.0",
"sass-loader": "^6.0.7",
"style-loader": "^0.20.3",
"stylelint-webpack-plugin": "^0.10.5",
"uglifyjs-webpack-plugin": "^1.2.5",
"webpack": "^4.8.3",
"webpack-cli": "^2.1.4"
Here are the relevant scripts in my package.json file, for reference in the comments:
"scripts": {
"watch": "./node_modules/.bin/webpack --mode development --watch --progress",
"build": "./node_modules/.bin/webpack --mode production"
},

The problem was the script I was using to run Webpack did not specify the config file. This is what it should look like:
"scripts": {
"watch": "./node_modules/.bin/webpack --watch --config webpack.dev.js",
},
I believe this was generating the #import problem because it was not loading the css-loader as without specifying the config file like above, it uses a default Webpack development config which does not include the css-loader.

As I mentioned in a comment on your question there's an open issue with Webpack 4 compatibility: https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/701
A fix for now is to install the alpha version of the library. I've done a small setup just now to test this and it works with webpack 4.
Install the alpha version npm i -D extract-text-webpack-plugin#next --save. Then install css-loader, sass-loader and node-sass.
Then in the webpack config file:
const ExtractTextPlugin = require('extract-text-webpack-plugin');
...
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: 'babel-loader'
},
exclude: /node_modules/,
include: path.join(__dirname, 'src')
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract(['css-loader', 'sass-loader'])
}
]
},
plugins: [
new ExtractTextPlugin('bundle.css'),
]
This correctly worked for me, and also concatenated multiple scss files that were using #import statements.
In package.json it should look like
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"webpack": "^4.8.3"
Edit: Just as a side note, apparently mini-css-extract-plugin works fine with webpack 4.

This worked for me: Replace your webpack styling config to the below code
module: {
rules: [
{
test: /\.(css|sass|scss)$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
},
{
loader: 'sass-loader'
}
]
}
]
}
I hope this resolves your issue thanks

Related

Webpack 4 basic React js hello world fails with "Module parse failed: Unexpected token"

Update:
Code pushed to https://github.com/gsouvik/react_spa_experiment
Initial Post:
I know there are hundreds of threads out there, some had typos in webpack config, some used the loaders in a wrong way, some got it solved, some still open. But after numerous tries I still cannot get this working, a simple "Hello World" using Webpack 4, React js.
What I did
I was following this video tutorial line by line:
React & Webpack 4 from scratch
My package.json
{
"name": "my_react_experiment_2",
"version": "1.0.0",
"description": "Basic react with webpack ",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --mode development --hot",
"build": "webpack --mode production"
},
"author": "Souvik Ghosh",
"license": "ISC",
"dependencies": {
"react": "^16.4.2",
"react-dom": "^16.4.2"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"html-webpack-plugin": "^3.2.0",
"webpack": "^4.17.1",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5"
}
}
My webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.export = {
entry: './src/index.js',
output: {
path: path.join(__dirname, '/build'),
filename: 'index_bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/templates/index.html'
})
]
};
My .babelrc
{
"presets": ["env", "react"]
}
My directory structure
Expected behaviour
I fire up the dev server npm run dev. Expected to see my shiny new React js page saying "My first React Webpack project" (from the component /components/App.js)
Actual Behavior
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('root'));
| //ReactDOM.render('Hello User ', document.getElementById('root'));
# multi (webpack)-dev-server/client?http://localhost:8080 (webpack)/hot/dev-server.js ./src main2
If required I can share the codebase via a git repo. Any help is greatly appreciated.
The issue is with typo in your webpack config file.
You have module.export which is not correct. It should be module.exports
Working example
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, '/build'),
filename: 'index_bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/templates/index.html'
})
]
};

Import js file in webpack / babel-loader not working in ios9 (ipad)

I run a cordova / Vue.js app with webpack
in my package.json :
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0"
...
}
in my webpack.config file :
const CONFIG = {
entry: {
app: ["babel-polyfill", path.join(PATHS.SRC_JS, 'app.js')],
},
output: {
path: PATHS.DIST,
//filename: 'app.bundle.js'
filename: './js/[name].js' //
},
module: {
rules: [
...
{
test: /\.js$/,
exclude: /node_modules\/(?!(swiper)\/).*/,
use: [
{
loader: 'eslint-loader',
options: {
emitWarning: true,
noConsole: 0
}
},
{
loader: 'babel-loader',
options: {
presets: [ 'env']
}
}
]
},
//.VUE FILES
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
};
module.exports = CONFIG;
and in my main app.js file,
if i write
console.log('app.js')
import style from '../css/sass/main.scss';
import config from '../assets/config.json';
and then i run webpack and cordova compilation, with output on ipad mini, it works, i have 'app.js' writed on console.
But if i add an import to js file (any file) :
import style from '../css/sass/main.scss';
import Preloader from './components/preloader-component.js';
import config from '../assets/config.json';
on ipad console i have an error :
SyntaxError : Unexpected token ')' in app.js:1
When building app with xcode on ios simulator, it works, but not on ipad (ios 9.3.5).
Need help !
Thanks
RESOLVED
Finally the problem was that Babel did not transpile ES6 correctly, so Safari on iOS would not read the code...
I simply put babel options in a .babelrc file, in place of in the webpack config file..and it works !!
Mysterious...
If someone has the same problem..

Testem receiving imports compiled to `require` when using ES2015/React presets to Babel

I have a project which is set up so that it builds with reactand jsx. It works fine to build it using node_modules/webpack/bin/webpack.js --config webpack.config.js and I can run the result in the browser with no problems. However, when I run npm test and view the test runner in the browser, I get the error: "Uncaught ReferenceError: require is not defined at dashboard-tests.js:3". It seems that webpack is compiling my tests (but not my normal code) into a version of javascriptthat can't be run in browsers.
Here are the relevant files:
.babelrc:
{
"presets": ["es2015", "react"]
}
testem.json:
{
"framework": [
"jasmine"
],
"launch_in_dev": [
"PhantomJS"
],
"launch_in_ci": [
"PhantomJS"
],
"serve_files": [
"tmp/**/*-test{,s}.js"
],
"on_start": "babel static_source --out-dir tmp",
"on_exit": "yes | rm -r tmp"
}
package.json:
{
"main": "index.js",
"scripts": {
"test": "testem"
},
"dependencies": {
"jquery": "^3.2.1",
"prop-types": "^15.6.0",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-feather": "^1.0.7"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"jasmine-es6": "^0.4.3",
"testem": "^1.18.4",
"webpack": "^3.6.0"
}
}
webpack.config.js:
var path = require("path");
var webpack = require('webpack');
module.exports = {
context: __dirname,
entry: './static_source/js/index.js',
output: {
path: path.resolve('./app/static/js/'),
filename: "compiled.js"
},
plugins: [],
module: {
loaders: [
{ test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
{ test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/ }
],
}
}
dashboard-tests:
import React from 'react';
import ReactDOM from "react-dom";
import TestUtils from "react-dom/test-utils";
import Dashboard from './dashboard';
describe('Dashboard', function() {
it('exists', function() {
expect(Dashboard).not.toBe(undefined);
});
it('renders arrows', function() {
var dashboard = <Dashboard />;
var renderedDashboard = TestUtils.renderIntoDocument(dashboard);
var arrowsDiv = TestUtils.findRenderedComponentWithClass('arrows');
expect(arrowsDiv).not.toBe(undefined);
});
});
You are using Babel to compile your test source files. Babel is just a transpiler, it takes ES+ files and translates them to ES5 files. Because import does not exist in ES5 Babel replaces them with require().
To fix the problem you need to bundle your source file into one, using Webpack.
You will need a separate Webpack configuration file, let's call it webpack.config.test.js. In this file we need to instruct Webpack to fetch all your static_source/**/*-test{,s}.js files as entry-points.
You will need the glob module : npm install glob --save-dev.
Then add the webpack.config.test.js file with this content :
var path = require("path");
var glob = require('glob');
var webpack = require('webpack');
module.exports = {
context: __dirname,
// we look for all file ending with -test(s?).js and return the absolute path
entry: glob
.sync('./static_source/js/**/*-test{,s}.js')
.map(function(file) { return path.resolve(__dirname, file) }),
output: {
// save the resulting bundle in the ./tmp/ directory
path: path.resolve('./tmp/'),
filename: "compiled.js"
},
plugins: [],
module: {
loaders: [
{ test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
{ test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/ }
],
}
}
On the testem.json file replace the on_start with a before_test to Webpack, and the serve_files to map to the bundled file.
"before_tests": "webpack --config webpack.config.test.js ",
"serve_files": [
"tmp/compiled.js"
],
When testem will be launched it will trigger the Webpack test compilation.
Now you should have a tmp/compiled.js file with all your test files bundled. You may need to do some tweaking but it should basically works.

webpack 2: ERROR in ./public/bundle.js from UglifyJs Unexpected character '`'

I got 2 related issues:
First: when I run npm run build the bundle.js file is not minified but I do get a bundle.js.map file.
Second: when I run webpack -d I only get a minified bundle.js file (and no error) but when I run webpack -p then I get a bundle.js that is not minified, a bundle.js.map, and those errors:
ERROR in ./public/bundle.js from UglifyJs
Unexpected character '`' [./app/config.js:5,0][./public/bundle.js:76,14]
ERROR in ./public/bundle.js from UglifyJs
Unexpected character '`' [./app/config.js:5,0][./public/bundle.js:76,14]
My question(s):
shouldn't the behaviors of webpack -p and webpack -d be the
opposite?
why is bundle.js not minified when I run npm run build?
why do I get those Unexpected character errors when I use template strings in my modules?
package.json looks like that:
{
...,
"scripts": {
"build": "webpack --progress --watch"
},
"devDependencies": {
"babel-core": "^6.13.2",
"babel-loader": "^6.2.5",
"babel-preset-es2015-native-modules": "^6.9.4",
"eslint": "^3.3.1",
"eslint-config-airbnb": "^10.0.1",
"eslint-plugin-html": "^1.5.2",
"eslint-plugin-import": "^1.13.0",
"eslint-plugin-jsx-a11y": "^2.1.0",
"eslint-plugin-react": "^6.1.2",
"webpack": "^2.1.0-beta.21"
}
}
while webpack.config.js is like that:
const webpack = require('webpack'); // eslint-disable-line import/no-extraneous-dependencies
const nodeEnv = process.env.NODE_ENV || 'production';
module.exports = {
entry: {
filename: './app/app.js'
},
output: {
filename: './public/bundle.js'
},
modules: {
loaders: [
{
test: /\.js?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015-native-modules']
}
}
]
},
devtool: 'source-map',
plugins: [
// uglify
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false },
output: { comments: false },
sourceMap: true
}),
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify(nodeEnv) }
})
]
};
I did search both here and Google (and webpack docs…) but I can't find anything useful to me. Thanks!!
UglifyJS2 does not have ES6/Harmony support in its releases yet. However, there's the Harmony branch which allows you to minify/uglify files with ES6 syntax.
I can suggest you an alternative solution which could help you spend less build time to transpile all ES6 to ES5.
Simply specify UglifyJs in your package.json, and let npm handles the dependencies.
"uglify-js": "git://github.com/mishoo/UglifyJS2#harmony-v2.8.22",

Webpack css-loader not building

I am having difficulty in getting CSS loading using css-loader on my JSX files. I was following the example from:
https://christianalfoni.github.io/react-webpack-cookbook/Loading-CSS.html
This is my JSX
import React from 'react';
import ReactDOM from 'react-dom';
import styles from './styles.css';
class Hello extends React.Component {
render() {
return <div>Hello world!</div>
}
}
var el = document.getElementById('content')
var data = JSON.parse(el.getAttribute('data-attr'))
ReactDOM.render(<Hello data={data} />, el);`
This is my package.json
"devDependencies": {
"babel-core": "^6.3.26",
"babel-loader": "^6.2.0",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"css-loader": "^0.23.1",
"exports-loader": "~0.6.2",
"expose-loader": "~0.6.0",
"grunt": "^0.4.5",
"grunt-babel": "^6.0.0",
"grunt-cli": "^0.1.13",
"grunt-contrib-watch": "^0.6.1",
"grunt-webpack": "^1.0.11",
"history": "^1.17.0",
"imports-loader": "~0.6.3",
"jquery": "^2.1.4",
"lodash": "~3.0.0",
"react": "^0.14.5",
"react-dom": "^0.14.5",
"react-router": "^1.0.3",
"style-loader": "^0.13.0",
"webpack": "^1.12.9",
"webpack-dev-server": "^1.14.0"
},
"dependencies": {
"chunk-manifest-webpack-plugin": "0.0.1",
"grunt-react": "^0.12.3"
}
This is my Webpack.config.js
var path = require('path');
var webpack = require('webpack');
var config = module.exports = {
// the base path which will be used to resolve entry points
context: __dirname,
// the main entry point for our application's frontend JS
entry: './app/frontend/javascripts/entry.js',
stats: {
// Configure the console output
colors: true,
modules: true,
reasons: true
},
progress: true,
keepalive: true,
module: {
loaders: [
{
test: /\.js?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader', // 'babel-loader' is also a legal name to reference
query: { presets: ['es2015', 'react'] }
},
{ test: /\.css$/, loader: "style-loader!css-loader" }
]
},
output: {
// this is our app/assets/javascripts directory, which is part of the Sprockets pipeline
path: path.join(__dirname, 'app', 'assets', 'javascripts'),
// the filename of the compiled bundle, e.g. app/assets/javascripts/bundle.js
filename: 'bundle.js',
// if the webpack code-splitting feature is enabled, this is the path it'll use to download bundles
publicPath: '/assets',
devtoolModuleFilenameTemplate: '[resourcePath]',
devtoolFallbackModuleFilenameTemplate: '[resourcePath]?[hash]',
},
resolve: {
// tell webpack which extensions to auto search when it resolves modules. With this,
// you'll be able to do `require('./utils')` instead of `require('./utils.js')`
extensions: ['', '.js'],
// by default, webpack will search in `web_modules` and `node_modules`. Because we're using
// Bower, we want it to look in there too
modulesDirectories: [ 'node_modules', 'bower_components' ],
},
plugins: [
// we need this plugin to teach webpack how to find module entry points for bower files,
// as these may not have a package.json file
new webpack.ResolverPlugin([
new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin('.bower.json', ['main'])
]),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
}),
//new webpack.optimize.CommonsChunkPlugin('common-bundle.js'),
//new webpack.optimize.CommonsChunkPlugin('public-bundle.js')
]
};
This is my styles.css
#div {
background-color: red;
}
The output I get from running my grunt task to run 'webpack' attached:
You can see where it says the build failed for the CSS.
cjs require fbjs/lib/mapObject [154] ./~/react/lib/ReactDOMFactories.js 18:16-45
[157] ./~/react/lib/onlyChild.js 1.21 kB {0} [built]
cjs require ./onlyChild [153] ./~/react/lib/ReactIsomorphic.js 24:16-38
[158] ./~/react/lib/deprecated.js 1.77 kB {0} [built]
cjs require ./deprecated [3] ./~/react/lib/React.js 19:17-40
[159] ./~/react-dom/index.js 63 bytes {0} [built]
cjs require react-dom [0] ./app/frontend/javascripts/entry.js 11:16-36
ERROR in ./app/frontend/javascripts/styles.css
Module parse failed: /Users/Booboo/Projects/Xeon/app/frontend/javascripts/styles.css Line 1: Unexpected token {
You may need an appropriate loader to handle this file type.
| div {
| background-color: red;
| }
# ./app/frontend/javascripts/entry.js 5:0-23
Warning: Task "webpack:dev" failed. Use --force to continue.
Aborted due to warnings.
Booboo$ grunt react && grunt webpack && grunt watch
I encounter this problem too.
But in my case, I found my loader was written as
{test: '/\.css$/', loader: 'style!css'}
which should be correctly written as
{test: /\.css$/, loader: 'style!css'}
note the '' around the /.css$/
I wise this would be helpful for you.
When you say
import styles from './styles.css';
you're trying to import a module that's not being exported as a module.
Try
import './styles.css';
instead to make it a simple file import.

Categories