I'm getting an error when running my react app: Uncaught SyntaxError: Unexpected token import
I know that there are a plethora of similar issues on here, but I think mine is a little different. First of all, here is the repository, since I'm not sure where exactly the error is: repo
I'm using create-react-app, and in a seperate backend directory I'm using babel (with a .babelrc file containing the preset es2015). The app worked fine until I added another file in a new directory in the backend folder (/backend/shared/validations/signup.js).
I was using es6 before that too, and it was working perfectly fine. First I thought it was some problem with windows, but I cloned the repo on my Ubuntu laptop and I'm getting the same error there.
Some things I tried already:
Move the entire folder from /backend to the root folder
Move just the file (signup.js) just about everywhere
So no matter where the file is, the error stays the same. If I remove the entire file and all references to it the app works again.
I think this error is pretty weird, considering I'm using es6 everywhere else in the app without trouble. It would be great if anyone could help me with this error.
edit: If you want to test this on your own machine just clone the repo and run npm start in the root folder (and also npm start in the backend folder, but that isn't required for the app to run, or for the error to show up).
That's what's happening:
Your webpack is set to run babel loader only in the src folder (include directive).
To change that, one approach is:
1) extract webpack configuration with npm run eject (don't know if there is another way to override settings in react-create-app). From the docs:
Running npm run eject copies all the configuration files and the
transitive dependencies (Webpack, Babel, ESLint, etc) right into your
project so you have full control over them.
2) in config/paths.js, add an appShared key, like that:
module.exports = {
/* ... */
appSrc: resolveApp('src'),
appShared: resolveApp('backend/shared'),
/* ... */
};
3) in config/webpack.config.dev.js, add the path to the babel loader, like that:
{
test: /\.(js|jsx)$/,
include: [ paths.appSrc, paths.appShared ],
loader: 'babel',
/* ... */
},
It works now!
Related
I've just switched to Preact 8.4.2 and would like to get the React Developer Tools to work as well. In my webpack.config.js, I've added:
alias: {
react: 'preact-compat',
'react-dom': 'preact-compat'
}
In my entry .js file, I've added:
require('preact/debug');
After adding these, I was getting an error when attempting to build:
Module parse failed: /myProject/node_modules/preact/src/preact.js Line 1: Unexpected token
You may need an appropriate loader to handle this file type.
| import { h, h as createElement } from './h';
| import { cloneElement } from './clone-element';
| import { Component } from './component';
# ./~/preact/debug.js 6:14-31
I only had .jsx files loading with babel-loader (not .js), so I added an additional entry in my webpack.config.js file:
{
test: /\.js$/,
include: /node_modules\/preact/,
loader: 'babel-loader'
},
After adding this entry, I'm able to build without issues, but my React Developer Tools just shows:
Waiting for roots to load...
to reload the inspector [click here]
Something is either up with your preact app or your webpack config. I just solved a similar problem.
First step, check if its your preact. If you have no console errors, drop your preact into this working boilerplate (you'll have to do a little rewiring to get it working) https://github.com/developit/preact-boilerplate
If after firing it up with your code, Devtools works as expected, then there is something wrong with your build. In that case it turns into a game of line by line updating your (mostly) working build to match preact-boilerplate.
In my case, I had included "src" in my webpack resolve. This threw no errors in terminal/console, and the build worked perfectly otherwise. Once I found it, devtools started working.
I'm testing CloudFoundry on IBM and are running NodeJS.
When trying to cf push my application I get the following error:
failed: The app upload is invalid: Symlink(s) point outside of root folder
In my appllcation I have the following code:
return res.sendFile(path.join(__dirname +'/tvshows/'+ guide +'.html'));
When not using path.join and simply use:
return res.sendFile(path.join('./tvshows/'+ guide +'.html'));
I get this error instead:
TypeError: path must be absolute or specify root to res.sendFile
What to do?
I've also tried stuff like path.join((process.env.BUILD_DIR || __dirname), and return res.sendFile('index.html', { root: path.join(__dirname, 'tvshows', guide) }); but no luck.
The fail came from my node_modules folder.
Adding .cfignore with node_modules/ fixed the issue.
You didn't mention the version of the cf cli that you're using, but I think that this is expected behavior starting with version 6.34.0.
push now preserves relative symlinks in app files. This makes it easier to work with Node.js apps using npm link, but note that it now errors when it detects a symlink pointing outside the app folder (e.g. a node_modules folder containing external symlinks).
https://github.com/cloudfoundry/cli/releases/tag/v6.34.0
I think you're running into the second part, "how errors when it detects a symlink pointing outside the app folder". It's nothing to do with the code in your app, but rather somewhere in your project folder there is a symlink which references another file that is not under the root of your project.
If you're on a unix-like system you can run find . -type l to find all the symlinks under the current directory. Then you just need to figure out which one is pointing outside of the project root.
Options are to remove that symlink, point it to something under your project root or use .cfignore to ignore that file (which is what you ended up doing).
Hope that helps!
I am running the webpack / webpack-dev-server portion of the base Vue.js Webpack template (https://github.com/vuejs-templates/webpack/) inside of a docker container I created. The container also contains the vue CLI in order to create new projects (you can get my container here if you want: https://hub.docker.com/r/ncevl/webpack-vue/).
Hot-reload does not work after moving from the webpack-simple template to this one.
Everything was working using the Webpack-Simple template which you can clone / see over here: https://github.com/vuejs-templates/webpack-simple
I was able to get the simple template running (with hot-reload working as intended) with the following webpack-development-server launch command:
webpack-dev-server --hot --inline --progress --host 0.0.0.0 --watch-poll
That said the full (not simple) version of the webpack template does not appear to use a webpack-dev-server launch command and instead appears to use additional middleware as referenced in build/dev-server.js (https://github.com/vuejs-templates/webpack/blob/master/template/build/dev-server.js) and the webpack dev config.
Since the --watch-poll was the key to getting the WDS hot-reload functionality to work within a docker container in the last project, my thinking is that I need to do something similar with the webpack-hot-middleware but I dont see anything in their docs (over here: https://github.com/glenjamin/webpack-hot-middleware) that talks about changing to a polling based approach.
I am not 100% sure the polling flag will do the trick since I can see the container recompile my source when I make a change. I can also see the change in my browser if I refresh it manually.
Whats stranger still is if I inspect my page in browser within chrome dev tools, and then head over to network / XHR I can see that the browser actually does receive information from the webpack-dev-server, but visually it does not update.
Give the above I assume websockets (or socket.io which I think is used) are working and communicating between the browser and the WDS so maybe this is a browser caching issue of some sort?
I checked in my console and found this so it is looking like a header issue:
For reference the text error from that image (to make it easier for anyone having the same issue to find this post) is:
EventSource cannot load http://__webpack_hmr/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://0.0.0.0:8080' is therefore not allowed access.
Again the Hot-Reload / Hot Module Reload was working with this identical container setup when using the webpack-simple Vue.js template.
I am wondering if anyone has run into anything similar or has any ideas on how to add the polling option . I guess my alternative would be roll back to a more basic webpack config and rebuild that portion of things to use the traditional webpack-dev-server / webpack config but give the above I am not sure that is going to fix it.
I am adding this as a separate answer since it more specifically answers the question in the title, while my other answer more specifically explains what solved my actual problem.
The vue.js webpack template project (which can either be init'd from the Vue CLI or pulled from its repo over here: https://github.com/vuejs-templates/webpack) separates its config files into several different directories.
I am posting this answer so that anyone who runs into the need to add polling to their project will be able to understand how / where to do that.
The base project structure for a Vue.js webpack template project looks like this:
The files that you care about if you are messing with trying to get hot module reload working are related to creating your server primarily with webpack-dev-middleware. The most important files related to that are highlighted here:
Basically if you want to add the polling code to the webpack-dev-middleware server you need to be in the /build/dev-server.js file on lines 20 to 24 that look like this:
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
quiet: true
})
To add polling you would add it just before or after quiet: true. As a side note, if you are having trouble with HMR I would change "quiet:true" to queit false to get a more verbose read out of whats going on from webpack-dev-middleware. I have included verbose and polling modifications to the above code here:
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
quiet: false, //Changed to for additional verbosity
watchOptions: { //Add Polling
aggregateTimeout: 300,
poll: 1000
}
})
My other answer is in regards to what ended up solving my problem, not necessarily how to actually add polling (which might be necessary for someone else but did not end up being needed to make my dockerized setup work).
It should also be noted that sometimes when HMR (webpack hot module reload) is not detecting changes it is due to the fact that webpack-hot-middleware or webpack-dev-middleware is running into an issue whereby some invisible characters are / were added to the name of the base project directory (probably by someone building the base Vue project) and therefore webpack on certain OSes is not able to see the changes.
If that happens to you and you are on OSx or running webpack inside of a docker container and you can't get HMR to detect changes, try to rename your vue-webpack project directory and it should work.
Ok. So I can't really take credit for this one since it was actually answered by Discuss user Cristian Pallarés over here: http://webpack.github.io/docs/webpack-dev-server.html#combining-with-an-existing-server
Christian says:
I was just trying the same. I just use "php artisan serve" on localhost:8000, and Webpack Dev Server on localhost:3000. You should make this:
set your webpack config "output.publicPath" as "http://localhost:3000/static/" instead of "/static/"
make your php application load this:
The key is the output.publicPath being absolute. Now, you should run "php artisan serve" and launch your webpack dev server too (in my case I use gulp).
Basically I took that and dug through the Vue.js Webpack Template files to locate the config file where webpack was looking for the public path. the public path setting ended up being in the index.js file located in the /config directory of the template.
I changed my code to look like this:
assetsSubDirectory: 'http://localhost:8080/static/', //!!Changed from /static/
assetsPublicPath: 'http://localhost:8080/', //!!Changed from /
As opposed to the previous setting which DID NOT WORK and looked like this:
assetsSubDirectory: '/static/',
assetsPublicPath: '/',
After that I was able to see my changes hot reload while running the vue.js Webpack template from within my docker container.
I used brunch-with-marionette skeleton available at: https://github.com/SimbCo/brunch-with-marionette Everything works fine for me but I don't know the necessary configuration in this skeleton to add requirejs-text plugin. I tried:
npm install requirejs-text
and it installed the plugin in node-modules folder but then when I tried to load a template like this:
items = require 'text!views/sub-menu/templates/panel'
the browser gives error about being unable to load file 'text!views/....'. It considers the whole thing a file name. Removing the "text!" part works but then it doesn't return the html text rather, it gives a function which is not what I need.
I even checked the installed plugin with "npm ls" command from the app folder but when it lists the node-modules, it says the following for requirejs-text:
npm ERR! extraneous: requirejs-text#2.0.12
I am working on this stuff for the first time. Kindly help me with the configuration to add requirejs-text plugin. Many thanks!
EDITED:
I am using coffeescript. Adding some code from search-menu-view.coffee file for reference:
SubMenuView = require 'views/sub-menu/sub-menu-view'
favorites = require 'models/favorites'
navTemplate = require 'text!views/sub-menu/templates/menu-panel'
module.exports = class SearchMenuView extends SubMenuView
template: 'views/sub-menu/templates/menu-search'
events:
'click .menu-search-btn-group': 'onSearchInputClick'
The first two files load fine. The third one which has text! in it, doesn't.
Architecture
I would like to share code between client and server side. I have defined aliases in the webpack config:
resolve: {
// Absolute paths: https://github.com/webpack/webpack/issues/109
alias: {
server : absPath('/src/server/'),
app : absPath('/src/app/'),
client : absPath('/src/client/'),
}
},
Problem
Now on the server side I need to include webpack in order to recognize the correct paths when I require a file. For example
require('app/somefile.js')
will fail in pure node.js because can't find the app folder.
What I need (read the What I need updated section)
I need to be able to use the webpack aliases. I was thinking about making a bundle of all the server part without any file from node_modules. In this way when the server starts it will use node_modules from the node_modules folder instead of a minified js file (Why? 1st: it doesn't work. 2nd: is bad, because node_modules are compiled based on platform. So I don't want my win files to go on a unix server).
Output:
Compiled server.js file without any node_modules included.
Let the server.js to use node_modules;
What I need updated
As I've noticed in https://github.com/webpack/webpack/issues/135 making a bundled server.js will mess up with all the io operation file paths.
A better idea would be to leave node.js server files as they are, but replace the require method provided with a custom webpack require which takes in account configurations such as aliases (others?)... Can be done how require.js has done to run on node.js server.
What I've tried
By adding this plugin in webpack
new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"ignore", /* filename= */"server.bundle.js")
Entries:
entry: {
client: "./src/client/index.js",
server: "./src/server/index.js",
ignore: ['the_only_node_module'] // But I need to do that for every node_module
},
It will create a file server.js which only contains my server code. Then creates a server.bundle.js which is not used. But the problem is that webpack includes the webpackJsonp function in the server.bundle.js file. Therefore both the client and server will not work.
It should be a way to just disable node_modules on one entry.
What I've tried # 2
I've managed to exclude the path, but requires doesn't work because are already minified. So the source looks like require(3) instead of require('my-module'). Each require string has been converted to an integer so it doesn't work.
In order to work I also need to patch the require function that webpack exports to add the node.js native require function (this is easy manually, but should be done automatically).
What I've tried # 3
In the webpack configuration:
{target: "node"}
This only adds an exports variable (not sure about what else it does because I've diffed the output).
What I've tried # 4 (almost there)
Using
require.ensure('my_module')
and then replacing all occurrences of r(2).ensure with require. I don't know if the r(2) part is always the same and because of this might not be automated.
Solved
Thanks to ColCh for enlighten me on how to do here.
require = require('enhanced-require')(module, require('../../webpack.config'));
By changing the require method in node.js it will make node.js to pass all requires trough the webpack require function which allow us to use aliases and other gifts! Thanks ColCh!
Related
https://www.bountysource.com/issues/1660629-what-s-the-right-way-to-use-webpack-specific-functionality-in-node-js
https://github.com/webpack/webpack/issues/135
http://webpack.github.io/docs/configuration.html#target
https://github.com/webpack/webpack/issues/458
How to simultaneously create both 'web' and 'node' versions of a bundle with Webpack?
http://nerds.airbnb.com/isomorphic-javascript-future-web-apps/
Thanks
Thanks to ColCh for enlighten me on how to do here.
require = require('enhanced-require')(module, require('../../webpack.config'));
By changing the require method in node.js it will make node.js to pass all requires trough the webpack require function which allow us to use aliases and other gifts! Thanks ColCh!
My solution was:
{
// make sure that webpack will externalize
// modules using Node's module API (CommonJS 2)
output: { ...output, libraryTarget: 'commonjs2' },
// externalize all require() calls to non-relative modules.
// Unless you do something funky, every time you import a module
// from node_modules, it should match the regex below
externals: /^[a-z0-9-]/,
// Optional: use this if you want to be able to require() the
// server bundles from Node.js later
target: 'node'
}