'Unexpected string' when running karma with webpack/babel - javascript

I'm trying to run karma using webpack to preprocess code with babel that can then be tested with mocha. However whenever I run it I get errors.
spec/tests.spec.js:
import 'chai/register-expect';
karma.conf.js:
const webpackConfig = require('./webpack.config.js');
const tests = './spec/**/*.spec.js'
module.exports = function(config) {
config.set({
singleRun: true,
browsers: ['Chrome'],
frameworks: ['mocha'],
files: [
tests
],
preprocessors: {
tests: ['webpack'],
},
webpack: webpackConfig,
})
}
webpack.config.js:
module.exports = {
mode: 'production',
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', {
'modules': false
}]
}
}
]
}
}
When I run karma I get the following output:
'Uncaught SyntaxError: Unexpected string\nat http://localhost:9876/base/spec/tests.spec.js?af68737606dd067ef21aa6efadfc004fb1d05454:1:8\n
Which corresponds to the import line.
If I remove all es6 code from the test, then it runs successfully, implying that webpack/babel isn't being invoked properly.
Any ideas why this isn't working?

So it was nothing to do with any of the tools, and turned out to be a JS gotcha.
In karma.conf.js I was doing:
const tests = './spec/**/*.spec.js'
...
preprocessors: {
tests: ['webpack'],
}
The problem here is that tests as an object key translates to the string "tests".
The solution was to use:
preprocessors: {
[tests]: ['webpack'],
}
So that tests gets expanded properly to the variable value.

Related

How do I get karma to set webpack's mode to development?

When I run karma, I'm getting the following warning:
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/
I tried adding mode: 'development' to my webpack-test.config.js file as suggested in the link above, but not only did that fail to make any difference, Intellij IDEA complained:
webpack: Property 'mode' is not allowed
My unit testing does run anyway, but I'd like to get rid of this warning. Any help is much appreciated.
Here's my webpack-test.config.js file:
const path = require('path');
const webpack = require('webpack');
const ROOT = path.resolve( __dirname, 'src' );
module.exports = {
mode: 'production',
context: ROOT,
resolve: {
extensions: ['.ts', '.js'],
modules: [
ROOT,
'node_modules'
]
},
module: {
rules: [
// PRE-LOADERS
{
enforce: 'pre',
test: /\.js$/,
use: 'source-map-loader'
},
// LOADERS
{
test: /\.ts$/,
exclude: [ /node_modules/ ],
use: 'ts-loader'
}
]
},
devtool: 'cheap-module-source-map',
devServer: {}
};
My karma.conf.js:
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('karma-webpack')
],
client:{
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
files: [
'spec.bundle.js'
],
preprocessors: {
'spec.bundle.js': ['webpack']
},
webpack: require('./webpack-test.config')
});
};
And spec.bundle.js:
const testsContext = require.context("./", true, /\.spec\.ts$/);
testsContext.keys().forEach(testsContext);
I'm launching karma via:
karma start ./karma.conf.js
I stumbled on this by trial and error, replacing:
webpack: require('./webpack-test.config')
...in karma.conf.js with:
webpack: {
mode: 'development'
}
...and the warning is gone. Not only that, I discovered that I really didn't need my webpack-test.config, nor the two npm modules I'd loaded to support it, source-map-loader and ts-loader.
If someone really did want to both specify mode: 'development' and specify a particular webpack config file, I'm not sure how they'd do it. I experimented with a few options and couldn't find anything that would work. This stuff doesn't have great documentation :(
You shouldn't have to require the webpack package in your config file. Not sure if that is causing Intellij to get confused or not, but mode is certainly a valid property of webpack.
https://webpack.js.org/concepts/mode/
I also noticed that in your karma.conf.js file, the line webpack: require('./webpack-test.config') is missing the .js extension for the config file. That may be why your config settings are not reflected in your karma test.

Module parse failed: Unexpected character but file should be plain Javascript

I'm trying to use react-syntax-higligther in an application built with webpack.
When I import
import SyntaxHighlighter from 'react-syntax-highlighter';
app compile and runs fine, but if I try to do an import for the styles:
import arta from 'react-syntax-highlighter/styles/hljs/arta';
the webpack compilation runs fine without errors, but when I try to run the application I have an error in the console:
index.bundle.js:35943 Uncaught Error: Module build failed:
ModuleParseError: Module parse failed: Unexpected character '�' (1:0)
I verified the imported file, and it is plain javascript, here below a portion:
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = {
"hljs": {
"display": "block",
"overflowX": "auto",
"padding": "0.5em",
"background": "#222",
"color": "#aaa"
},
"hljs-subst": {
"color": "#aaa"
},
and furthermore usually these kind of errors arises during webpack compilation, this appear to be a message generated compile time and added to the generated code... I don't understand what is wrong.
ADDITION
Apparently the error is random, since I'm using webpack --watch to compile when file changes, if force recompile by exiting webpack --watch and running it again... it works! Any idea?
for completeness: webpack configuration here below:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
// Constant with our paths
const paths = {
DIST: path.resolve(__dirname, 'dist'),
JS: path.resolve(__dirname, 'src'),
SRC: path.resolve(__dirname, 'src'),
};
// Webpack configuration
module.exports = {
entry: path.join(paths.JS, 'index.js'),
output: {
path: paths.DIST,
filename: 'index.bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(paths.SRC, 'index.html'),
}),
new ExtractTextPlugin('style.bundle.css'),
],
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [
'babel-loader',
],
},
// Files will get handled by css loader and then passed to the extract text plugin
// which will write it to the file we defined above
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
use: 'css-loader',
}),
} ,
{
test: /\.(eot|svg|ttf|woff|woff2|png)$/,
loader: 'file-loader',
}
],
},
resolve: {
extensions: ['.js', '.jsx'],
},
watchOptions: {
aggregateTimeout: 300,
poll: 1000
}
};

Transpiling in Webpack 2

I added
Babel Preset ENV
as well as babel-plugin-syntax-dynamic-import to my plugins to make it work, everything works fine now, however it still wont load in ie11, can't figure out why?
webpack.config:
const webpack = require('webpack');
const pkg = require('./package.json');
const path = require('path');
const debug = process.env.NODE_ENV !== 'prod';
module.exports = {
context: __dirname,
devtool: 'sourc-emap',
entry: {
app: `${pkg.paths.src.js}index.js`,
},
output: {
path: path.resolve(__dirname) + pkg.paths.src.assets,
filename: '[name].bundle.min.js',
publicPath: '/assets/',
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.js$/,
loader: 'eslint-loader',
exclude: /node_modules/,
},
],
},
plugins: debug
? [
]
: [
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
// new webpack2.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }),
],
};
.babelrc:
{
"presets": [
["es2015"],
["env", {
"targets": {
"browsers": ["last 2 versions", "safari >= 7", "ie 10-11"]
}
}]
],
"plugins": ["babel-plugin-syntax-dynamic-import",
"babel-plugin-add-module-exports"
]
}
my entry index.js:
const jsLoader = document.querySelector('.js-loader');
if (jsLoader) {
import('./modules/loader.js')
.then(module => module.loader);
}
and the module loader.js
const jsLoader = document.querySelector('.js-loader');
// hide loader on pageload
window.onload = function init() {
jsLoader.style.display = 'none';
};
export default jsLoader;
its just a simple loader that should be hidden after the page loaded, only to figure out if it works in older browsers
i figured that i don't have to use a babel loader for transpiling the es2015 code since webpack 2 will do it
webpack 2 does support the es2015 module syntax, and webpack 2 can successfully parse the es2015 language features out of the box. However, this does not guarantee your browser will, nor will webpack transform the module features.
Babel Preset ENV
In a situation like this, we recommend you use the the babel preset babel-preset-env. This will allow you to specify which browsers you are looking to support, and then subsequently leverage babel and babel-loader to only transpile the changes that are not natively supported.

Karma unit test for ES6 modules with babel

I'm following instructions from karma-babel-preprocessor to set up unit tests in a project I'm currently working, but I always the error
'require is not defined'
My karma.conf.js is as follows:
files: [
{ pattern: './test/unit/*.spec.js', watched: true },
{ pattern: './src/js/es6_modules/*.js', watched: false },
],
preprocessors: {
'./src/js/es6_modules/*.js': ['babel'],
'./test/unit/*.spec.js': ['babel'] //, 'coverage'
},
babelPreprocessor: {
options: {
presets: ['es2015'],
sourceMap: 'inline'
},
filename: function (file) {
return file.originalPath.replace(/\.js$/, '.es5.js');
},
sourceFileName: function (file) {
return file.originalPath;
}
}
The scripts in src/js/es6_modules jave ES6 classes exported. Something like:
export default class MyClass {
}
And my spec file would need to import this
import { MyClass } from "../../src/js/es6_modules/myclass";
I have seen some thread here at SO that said I would need to use browserify, but I can't find any doc (or example) on how to use it together with babel in karma. Does anyone know to configure this properly?
I fixed it using browserify instead of babel, and using a babelify transform
preprocessors: {
'./src/js/es6_modules/*.js': ['browserify'],
'./test/unit/*.spec.js': ['browserify']
},
browserify: {
debug: true,
"transform": [
[
"babelify",
{
presets: ["es2015"]
}
]
]
},

no window object present webpack nodejs

I'm using webpack with babel to compile my ecmascript 6 code. Everything works fine but if I add certain dependeciens like the requests npm package. Here are my files:
main.js
import os from 'os'
export class User {
constructor(username) {
this.username = username;
}
register() {
console.log("registering...");
}
}
var client = new User("hey")
console.log(user.register());
webpack config:
var webpack = require('webpack')
module.exports = {
entry: [
'./src/main.js'
],
output: {
path: "dist",
publicPath: "/dist/",
filename: "stela.js"
},
watch: false,
module: {
loaders: [{
test: /\.js$/,
// excluding some local linked packages.
// for normal use cases only node_modules is needed.
exclude: /node_modules/,
loader: 'babel'
}, {
test: /\.json$/,
loader: 'json-loader'
}]
},
externals: {
fs: '{}',
tls: '{}',
net: '{}',
console: '{}'
},
babel: {
presets: ['es2015'],
plugins: ['transform-runtime']
},
resolve: {
modulesDirectories: ['node_modules']
}
}
Now if I run webpack and then run node dist/stella.js everything works fine it logs out registering...; however, if I add certain dependencies like the requests npm package:
...
import request from 'request'
...
I run webpack everything compiles down with no errors but then I try running node dist/stella.js and I get this error:
throw new Error('no window object present');
By default, Webpack is set up to target the browser, not a Node environment. Try setting target in your config:
module.exports = {
// ...
target: "node",
// ...
}

Categories