Unexpected token '#' when using ES6 decorators - javascript

I have a React project setup and I'm trying to incorporate MobX into it. With that I have to use decorators i.e.
#observable
When I do that though I get the following error:
https://github.com/mobxjs/mobx
Module build failed: SyntaxError: Unexpected token (5:22)
class ListStore {
#observable items = ['Pete', 'John', 'Henry', 'Jeff', 'Bob'];
}
My Webpack config:
module.exports = {
entry: './src/App.js',
output: {
path: __dirname,
filename: 'app.js'
},
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'react'],
plugins: ['transform-decorators-legacy']
}
},
{
test: /\.scss?$/,
exclude: /node_modules/,
loaders: ['style', 'css', 'sass']
}]
}
};
My ESLint config:
{
"parserOptions": {
"ecmaVersion": 6,
"ecmaFeatures": {
"jsx": true
},
"sourceType": "module"
},
"env": {
"browser": true,
"node": true,
"es6": false
},
"ecmaFeatures": {
"modules": true
},
"rules": {
"strict": [
2,
"global"
],
"quotes": [
2,
"single"
],
"indent": [
2,
4
],
"eqeqeq": [
2,
"smart"
],
"semi": [
2,
"always"
],
"max-depth": [
2,
4
],
"max-statements": [
2,
15
],
"complexity": [
2,
5
]
}
}
As a note, I'm new to using Webpack as well as utilising ESLint, so this might very well be a newby question. However after doing research online I haven't find anything that's worked. (This includes installing the 'transform-decorators-legacy' Babel plugin).

I think that the issue isn't so much the decorator, but the property initializer syntax. It'll probably fail on this as well:
class ListStore {
items = ['Pete', 'John', 'Henry', 'Jeff', 'Bob']
}
To support those, you can add the transform-class-properties plugin:
$ npm install babel-plugin-transform-class-properties --save
(and update your Webpack config accordingly)
Or use a Babel preset that includes it (stage-2, stage-1 or stage-0).

Related

Possible spread error on IE 11 (Webpack, VueJS)?

I'm getting this error on IE 11:
Here are my webpack and babel configuations:
webpack configuration
const path = require('path');
const webpack = require('webpack');
const { VueLoaderPlugin } = require('vue-loader');
const StylishWebpackPlugin = require('webpack-stylish');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const withLogRocket = process.argv.includes('--with-logrocket');
if (withLogRocket) {
/* eslint-disable no-console */
console.info('-> Building with LogRocket enabled.');
/* eslint-enable */
}
// Base webpack configuration for all environments.
module.exports = {
context: path.dirname(__dirname),
entry: {
app: './src/main.js',
},
target: 'web',
output: {
filename: '[name].[contenthash].js',
hashDigestLength: 8,
},
resolve: {
extensions: ['.ts', '.js', '.vue'],
alias: {
'#': path.resolve(__dirname, '../src'),
},
},
module: {
rules: [
{
test: /\.js/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
},
{
loader: 'ts-loader',
options: {
transpileOnly: true,
},
},
],
},
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
],
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
],
},
],
},
stats: 'errors-only',
plugins: [
new VueLoaderPlugin(),
new ForkTsCheckerWebpackPlugin({
tslint: true,
reportFiles: ['src/**/*.ts'],
}),
new StylishWebpackPlugin(),
new webpack.DefinePlugin({
USE_LOGROCKET: withLogRocket,
}),
],
};
babelrc file
{
"presets": ["env"],
"plugins": [
"transform-es2015-destructuring",
"transform-object-rest-spread"
]
}
I'm not really sure if this is due to the ...sources spread or among others. I'm pretty sure I have the babel-transform-object-rest-spread package but I still don't get why I have this error, I also used babel-preset-env. As you can see on the configuration I am running a pure JS (VueJS, typescript) app. I've read numerous posts about using polyfill and among others but it didn't help me make our app run on IE11.
You're using env preset but never defining what environment Babel is supposed to generate code for (so I assume IE 11 is not supported in that case).
Without any configuration options, babel-preset-env behaves exactly the same as babel-preset-latest (or babel-preset-es2015, babel-preset-es2016, and babel-preset-es2017 together).
So just add the options object having the targets property set to something the like of
"browsers": [ "last 1 version", "ie >= 11" ]
like this:
{
"presets": ["env", {
"targets": {
"browsers": [ "last 1 version", "ie >= 11" ]
}
}],
"plugins": [
"transform-es2015-destructuring",
"transform-object-rest-spread"
]
}
I also highly recommend you switch to Babel 7 asap.

ESLint failing on relative imports with webpack

I have been trying to get eslint working in an existing project, following the airbnb style guide. I have most of it working, but I can't get the relative imports that I use to pass linting. an example of one of my relative imports is:
import { actions as practiceActions } from 'reducers/practice';
which give the following linting error.
Unable to resolve path to module 'reducers/practice'
my .eslintrc.json is as follows:
{
"env": {
"browser": true,
"mocha": true
},
"extends": ["airbnb-base"],
"globals": {
"spy": true,
"stub": true,
"mount": true,
"shallow": true,
"chai": true,
"expect": true,
"sinon": true,
"getStoreAction": true,
"getMockStore": true,
"render": true
},
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"plugins": [
"react"
],
"rules": {
"semi": 2,
"max-len": [1, 100, 2],
"indent": ["error", 4],
"import/extensions": ["warn", "never"],
"react/jsx-uses-vars": "error",
"react/jsx-uses-react": "error"
},
"settings" : {
"import/extensions": ["js", "jsx", "png"],
"import/resolver": { //note that I have also tried just using "webpack" as the resolver, with the same outcome.
"node": {
"extensions": [".js",".jsx"]
}
},
"import/ignore": ["node_modules", ".(scss|less|css)$"]
}
}
My webpack config is quite long, but it's the default from create react app. There have been no manual changes to this.
module.exports = {
devtool: 'cheap-module-source-map',
entry: [
require.resolve('./polyfills'),
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appIndexJs,
],
output: {
pathinfo: true,
filename: 'static/js/bundle.js',
chunkFilename: 'static/js/[name].chunk.js',
publicPath: publicPath,
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'),
},
resolve: {
modules: ['node_modules', paths.appNodeModules].concat(
process.env.NODE_PATH.split(path.delimiter).filter(Boolean),
),
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
alias: {
'react-native': 'react-native-web',
},
plugins: [
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
],
},
module: {
strictExportPresence: true,
rules: [
{
test: /\.(js|jsx|mjs)$/,
enforce: 'pre',
use: [
{
options: {
formatter: eslintFormatter,
eslintPath: require.resolve('eslint'),
},
loader: require.resolve('eslint-loader'),
},
],
include: paths.appSrc,
},
{
oneOf: [
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]',
},
},
// Process JS with Babel.
{
test: /\.(js|jsx|mjs)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
cacheDirectory: true,
},
},
{
test: /\.module.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
modules: true,
localIdentName: '[path]__[name]___[local]',
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
},
{
test: /\.css$/,
exclude: /\.module\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
},
{
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
],
},
],
},
plugins: [
new InterpolateHtmlPlugin(env.raw),
new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
}),
new webpack.NamedModulesPlugin(),
new webpack.DefinePlugin(env.stringified),
new webpack.HotModuleReplacementPlugin(),
new CaseSensitivePathsPlugin(),
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
],
node: {
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
},
performance: {
hints: false,
},
Everything else seems to work fine linting-wise, and the relative imports are working in the application. I just can't get them to be recognized by my linter.
I'd recommend taking a further look at the docs for eslint-plugin-imports webpack resolver. Specifically, try passing the location of your webpack config explicitly in .eslintrc.json:
{
// ...
"settings": {
"import/resolver": {
"webpack": {
"config": "my.webpack.config.js"
}
}
// ...
}
}
Hopefully that causes the resolver to pick up all resolve options in the webpack config.

Using babel plugin in webpack configuration file

In their website, webpack shows plugin usage like this
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({template: './src/index.html'})
]
I want to use babel plugin transform-async-to-generator, so I added it in babelrc file but I dont know this is enough, should I add it also webpack file ? If so how
I can not be sure if writing plugin in webpack config file required because right now I am getting runtime error and not sure if it works writing only in babelrc file.
my current webpack config file
var path = require('path')
module.exports = {
entry: path.resolve(__dirname, 'partner/index.js'),
output: {
path: path.resolve(__dirname, './dist'),
filename: 'partner_bundle.js'
},
target: 'web',
module: {
rules: [
{
test: /\.js$/, // Check for all js files
loader: 'babel-loader',
query: {
presets: [
'babel-preset-env',
'babel-preset-stage-0'
].map(require.resolve)
},
exclude: /node_modules\/(?!other-module)/
}
]
},
stats: {
colors: true
},
devtool: 'source-map',
resolve: { symlinks: false }
}
babelrc file
{
"presets": [
"env",
"stage-2"
],
"plugins": [
"transform-async-to-generator",
"transform-async-generator-functions",
[
"transform-runtime",
{
"helpers": false,
"polyfill": false,
"regenerator": true
}
]
]
}
Here you can see in my webpack config how I include the babel plugins:
test: /(\.jsx|\.js)$/, // JSX and JS files should be present.
exclude: /(node_modules|bower_components)/,
use: [{
loader: 'babel-loader',
options: {
// Babel must be required like this to be able to use npm-link to link to shared code, see:
// https://stackoverflow.com/questions/34574403/how-to-set-resolve-for-babel-loader-presets/
presets: [
[node_modules + '/#babel/preset-env', {
// Ref: 1) http://2ality.com/2017/02/babel-preset-env.html
// 2) http://caniuse.com/usage-table
// In case it supports the browserlist in package.json, remove this here, see:
// https://github.com/babel/babel-preset-env/issues/149
"targets": {"browsers": ["> 4%", "safari 10", "ie 11", "iOS 9"]},
"modules": false,
"useBuiltIns": 'entry',
// "debug": true
}],
[node_modules + '/#babel/preset-react'],
],
plugins: [
node_modules + '/#babel/plugin-proposal-class-properties',
node_modules + '/#babel/plugin-proposal-object-rest-spread'].map(require.resolve)
}
}]

How to setup webpack for supporting ES6 Modules in Node

I'm using Webpack for bundle client and server code, so my webpack.config.js looks like:
module.exports = [
{ /* client config */ },
{ /* server config */ },
];
I want to write ES6 (modules) in both and transpile code to ES5 using Babel.
For client, this can be done with babel-loader:
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: [
'react',
[
'env',
{
targets: {
'browsers': 'last 2 versions',
},
},
],
],
},
}
Based on this, I wrote babel loader for server:
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: [
'react',
[
'env',
{
targets: {
'node': 'current',
},
},
],
],
},
}
Something tells me that babel-loader will never work for this purpose.
After ran webpack, bundles are right located but server entry point (server.js) aren't transpiled correctly:
SyntaxError: Unexpected token import
Generally when we want to transpile Node code, we would use babel-cli package and add a script in package.json:
"scripts": {
"build": "babel src -d dist"
}
and manually:
npm run build
My question is: How to setup ES6 transpiling with Babel for Node inside webpack.config.js?
+BONUS
webpack.config.js
const path = require('path');
const babelRcClient = {
presets: [
'react',
[
'env',
{
targets: {
'browsers': 'last 2 versions',
},
},
],
],
};
const babelRcServer = {
presets: [
'react',
[
'env',
{
targets: {
'node': 'current',
},
},
],
],
};
const babelLoaderClient = {
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: babelRcClient,
};
const babelLoaderServer = {
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: babelRcServer,
};
module.exports = [
{
context: __dirname,
entry: './shared/index.js',
output: {
path: path.resolve(__dirname, './static'),
filename: 'bundle.js',
},
module: {
loaders: [
babelLoaderClient,
],
},
plugins: [],
},
{
context: __dirname,
entry: './server/server.js',
target: 'node',
output: {
path: path.resolve(__dirname, './build'),
filename: 'server.js',
libraryTarget: 'commonjs',
},
externals: [ /^(?!\.|\/).+/i, ],
module: {
loaders: [
babelLoaderServer,
],
},
plugins: [],
},
]
By specifying
targets: {
'node': 'current',
}
you are telling babel to transpile your code to node version which you are using to transpile the code.
Are you using the same node version on production?
Try specifying numeric node version, e.g. 6.11.2 and then run transpilation.
Another thing you can do is tell babel to leave ES6 modules in ES6 way and don't replace it with commonjs approach (which is default) by setting:
targets: {
'node': ...,
},
modules: false
This thing worked for me. Try and check once.
{
test: /\.(js|jsx)$/,
include: [].concat(
path.resolve('./app') //path to your application
),
use: ['babel-loader']
}

"Unexpected token import" angular 2 external module

I'm using the ngx-magicsearch module in my project with. However, I get the following error:
Uncaught SyntaxError: Unexpected token import.
I am using the version of Angular 4.2.5, Webpack version 1.15.0 and Typescript 2.3.4
Here is my Webpack file:
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
'app': './app/app.module.ts',
'vendor': './app/vendor/vendor.ts'
},
resolve: {
extensions: ['', '.ts', '.js', '.css', '.html'],
modulesDirectories: ["node_modules", "assets\\js"]
},
output: {
filename: '[name].bundle.js',
},
module: {
noParse: [/jszip.js$/],
loaders: [{
test: /\.ts$/,
loaders: [
'awesome-typescript-loader',
'angular2-router-loader'
]
},
{
test: /\.html$/,
loader: 'html'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)(\?.*$|$)/,
loader: 'file?name=assets/[name].[hash].[ext]'
},
{
test: /\.css$/,
exclude: './app',
loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
},
{
test: /\.css$/,
include: './app',
loader: 'raw'
},
{
test: /[\\\/]assets[\\\/]js[\\\/]modernizr\.min\.js$/,
loader: "imports?this=>window!exports?window.Modernizr"
}
]
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
KJUR: "jsrsasign-latest-all-min",
b64utoutf8: "base64x",
dateFormat: "dateformat",
moment: "moment"
}),
new ExtractTextPlugin('[name].bundle.css'),
new webpack.optimize.CommonsChunkPlugin({
name: ['app', 'vendor']
})
],
devServer: {
historyApiFallback: true,
stats: 'minimal'
}
};
tsconfig.js:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"noEmitHelpers": false,
"sourceMap": true,
"preserveConstEnums": true,
"alwaysStrict": true
},
"exclude": [
"node_modules"
],
"compileOnSave": false,
"buildOnSave": false
}
And the errors:
The entry point of ngx-magicsearch uses ES modules. You would need to transpile them with babel to use it. Usually the packages publish a transpiled version, although many of them now also publish a version with ES modules that can be used by bundling tools that support them. ES modules are supported out of the box, since webpack 2.
It is highly recommended to upgrade webpack. You'll have to adapt your config a little. For details have a look at the official migration guide.

Categories

Resources