Making export default work with Babel, webpack and Node.js - javascript

I can't figure out why my code doesn't work.
I am building a ES6 style class and want to export it to be able to use it somewhere else in the server side. I put the code into a file called PlayerManager.jsin the server folder.
I put my client code in the src folder. And my server code in my server folder and server.js outside of server folder.
Here is the directory structure:
Root
- dist
- node_modules
- public
- server
- src
server.js
webpack.base.js
webpack.dist.js
package.json
.babelrc
PlayerManager.js file:
class PlayerManager {
constructor() {
if (! PlayerManager.instance) {
this.playerList = {};
this.bulletList = {};
this.initPack = {player: [], bullet: []};
this.removePack = {player: [], bullet: []};
PlayerManager.instance = this;
}
return PlayerManager.instance;
}
resetData() {
this.initPack.player = [];
this.initPack.bullet = [];
this.removePack.player = [];
this.removePack.bullet = [];
}
}
const instance = new PlayerManager();
Object.freeze(instance);
export default instance;
However, when I use npm run dev which runs node server.js it throws an error saying
export default instance;
^^^^^^
SyntaxError: Unexpected token export
at Object.exports.runInThisContext (vm.js:53:16)
Here is the configuration for babel in webpack:
const path = require('path');
var CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: {
main: './src/main'
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].bundle.js'
},
plugins: [
new CopyWebpackPlugin([
{ from: 'public/img',
to: 'static' },
{ from: 'public' }
])
],
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
//include: path.join(__dirname, 'src')
exclude: [
path.resolve(__dirname, "node_modules"),
],
},
{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=90000' }
]
},
resolve: {
extensions: ['', '.js']
}
};
In .babelrc:
{
"presets": [
"es2015"
],
"sourceRoot": "./src"
}
In my package.json file:
"scripts": {
"build": "npm run lint && npm run release",
"lint": "./node_modules/.bin/eslint ./src/**/*.js",
"dev": "node server.js",
"release": "NODE_ENV=production webpack --config ./webpack.dist.js --progress",
"test": "./test/*.test.js --compilers js:babel-core/register --recursive --reporter spec"
},

Webpack is a bundler for producing packages that run on the client (in the browser), it is not aware of or concerned with code on the server. (Unless you are doing universal application stuff.)
You will notice too that your npm dev script is simply asking node to load the server.js file, which is (correctly) not mentioned anywhere in your Webpack config.
You are looking for babel-register:
One of the ways you can use Babel is through the require hook. The require hook will bind itself to node’s require and automatically compile files on the fly.
Create an "entry" file that first requires babel-register and then requires your server.js file:
// server-entry.js
require('babel-register')
require('./server.js')
Now change your npm dev script to be node server-entry.js.
______
Aside: it is necessary to create an entry file as babel-register cannot transpile the file in which it is invoked. For example, this would fail:
// server.js
require('babel-register')
export default function () {}

Related

mocha-webpack not finding tests

I can't seem to figure how to get mocha-webpack to detect tests in my folder. I'm running the following command:
mocha-webpack --webpack-config test/server/webpack.config-test.js
webpack.config-test.js
var nodeExternals = require("webpack-node-externals")
const path = require("path")
function resolve(dir)
{
return path.join(__dirname, "..", dir)
}
module.exports = {
context: path.resolve(__dirname),
resolve: {
extensions: [".js"],
alias: {
"vue$": "vue/dist/vue.esm.js",
"#": resolve("src"),
}
},
target: "node", // webpack should compile node compatible code
externals: [nodeExternals()], // in order to ignore all modules in node_modules folder
}
If it helps, I'm also using vue-cli, so there are already webpack configs, and maybe I could just import one of them then do slight changes.
You need to add this to your line of code:
mocha-webpack --webpack-config test/server/webpack.config-test.js \"src/**/*.js\"

How to auto-rebuild bundle with webpack-dev-server without run command again?

I'm a newbie in webpack and I'm using webpack 4 for my project. But I have a problem, I have some file scripts. In the first time to build with webpack dev server, it's run okay. But when server running, I continue create a new file script(example: c.js), rename or delete the exist file the server not auto build this script to main.js. How can automatic webpack rebuild my new file(c.js) to main.js without run command again?
This is my repo on github:
https://github.com/aiduc93/webpack4-scss-pug-es6
You can follow this step to reproduce my problem:
Step 1: start server with 'npm run dev' and run localhost:3000 in browser.
Step 2: when server running, we create new file(c.js), you can copy my code in hide.js or show.js and change the pluginName to 'anything'(ie: pluginName='clickable')
Step 3: go to index.pug, create new p tag with data-clickable(ie: p(data-clickable) clickable)
Step 4: refresh page in browser and click to text clickable. Js will not run because it not recompile.
This is my structure
//folder javascript in project
javascript
| hide.js
| show.js
| server.js
//folder dist after build
dist
| main.js
This is script in package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --inline --hot",
"build": "webpack --mode production"},
This is webpack.config.js
const path = require('path');
const glob = require('glob');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin')
module.exports = {
entry: { main: glob.sync('./src/**/*.js*')} ,
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js',
},
devtool: 'inline-source-map',
watch: true,
module: {
rules: [
{
test: /\.pug$/,
use: ["html-loader", "pug-html-loader"]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: ["babel-loader"]
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract(
{
fallback: 'style-loader',
use: [ 'css-loader', 'sass-loader']
})
},
{
type: 'javascript/auto',
test: /\.json$/,
use: [
{
loader: 'file-loader',
options: {
name: "./plugin-config/[name].[ext]"
}
}
]
}
]
},
devServer: {
contentBase: path.join(__dirname, "dist"),
compress: true,
inline: true,
port: 3000,
// historyApiFallback: true,
hot: true
},
plugins: [
new ExtractTextPlugin(
{ filename: 'style.css'}
),
new CleanWebpackPlugin('dist', { watch: true,
}),
new HtmlWebpackPlugin({
inject: false,
hash: true,
template: './src/index.html',
}),
new WebpackMd5Hash(),
]
};
In webpack 4 only real entry-points are entry-points, this means, no vendor-scripts, plugins...in entry.
You cannot use glob here beause it creates an array of all js-files and only server.js is your real entry-point for your application!
Adding a js-file to your wp project doesn't mean it will be compiled as you don't reference it anywhere, so wp cannot know that it is needed.
WP creates a dependency graph starting from the dependencies of your entry-point(s) and creates the bundle(s).
Your server.js is your entry-point and should look like this:
import "../stylesheets/style.scss";
import $ from 'jquery';
import "./clickable" // without import no recompile!
import "./hide"
import "./show"
console.log("his");
console.log("hello, world23");
The entry-point in your webpack.config.js:
module.exports = {
entry: {
main: path.resolve(__dirname, "./src/javascripts/server.js")
},

Jest test 'unexpected token export'

I'm trying to get my jest tests to run. I am getting the error SyntaxError: Unexpected token export at the line export default configureStore..specifically on the word 'export'. To me this suggests redux-mock-store is not being transpiled by Babel, so how can I force this with Jest? I'm using jest-webpack.
ContractsActions.test.js
import * as contractsActions from './contractsActions';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
const middlewares = [thunk]
const mockStore = configureMockStore(middlewares);
describe('async actions', () => {
const store = mockStore({})
return store.dispatch(contractsActions.fetchAllContracts()).then(() => {
//Do something
})
});
package.json
...
"scripts": {
"test": "jest-webpack",
...
"jest": {
"transformIgnorePatterns": [
"!node_modules/"
]
}
...
webpack.config.js
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query:
{
presets:['es2015', 'react', 'stage-2']
}
}
]
},
resolve: {
extensions: ['.js', '.jsx'],
alias: {
react: path.resolve('./node_modules/react'),
}
},
I ended up fixing this problem by creating a separate .babelrc file, instead of trying to set the babel configuration settings in package.json. I'm sure there are other steps I tried that may have contributed but this seemed to be the one that fixed it.
.babelrc
{
"presets": [["es2015", {"modules": false}]],
"env": {
"test": {
"plugins": ["transform-es2015-modules-commonjs"]
}
}
}
Take a look at the package.json from that package:
https://github.com/arnaudbenard/redux-mock-store/blob/master/package.json
You can see it offers different entry points:
"main": "dist/index-cjs.js",
"module": "dist/index-es.js",
"js:next": "dist/index-es.js",
"browser": "dist/index.min.js",
Check if your node_modules/redux-mock-store has a dist folder. If not, start the build that suits your requirements (also listed in package.json):
"build:cjs": "babel src --out-file dist/index-cjs.js",
"build:umd": "cross-env BABEL_ENV=es NODE_ENV=development rollup -f umd -c -i src/index.js -o dist/index-umd.js",
"build:umd:min": "cross-env BABEL_ENV=es NODE_ENV=production rollup -f umd -c -i src/index.js -o dist/index-umd.min.js",
"build:es": "cross-env BABEL_ENV=es NODE_ENV=development rollup -f es -c -i src/index.js -o dist/index-es.js",
"build": "npm run build:umd && npm run build:umd:min && npm run build:es && npm run build:cjs",
I don't know which of those versions buildable would be the right one for you, but I assume one of them will be. At worst, start npm i && npm run build:cjs in node_modules/redux-mock-store and resort to CommonJS require syntax:
const configureMockStore = require('redux-mock-store/dist/index-cjs.js');
Really hope this solves your problem, at least these are the steps I would try.

How to put React in production mode?

I tried using the solution from here but the icon is still read indicating dev mode.
Here is my current file with updates from the answer below:
const path = require('path');
const SRC_DIR = path.join(__dirname, '/client-react/src');
const DIST_DIR = path.join(__dirname, '/client-react/dist');
const webpack = require('webpack')
module.exports = {
entry: `${SRC_DIR}/index.jsx`,
output: {
filename: 'bundle.js',
path: DIST_DIR
},
plugins: [
new webpack.DefinePlugin({'process.env': {NODE_ENV: JSON.stringify('production')} })
],
module: {
loaders: [
{
test: /\.jsx?/,
include: SRC_DIR,
loader: 'babel-loader',
query: {
plugins: ["transform-object-rest-spread", "transform-class-properties"],
presets: ['react', 'es2015']
}
}
]
}
};
If you use Webpack 4, you don't need to change webpack.config.js. It remains the same in both development and production modes.
The only thing needed is in your package.json:
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
}
Having this, to create a development bundle:
npm run dev
Production bundle:
npm run build
When you want to build your app in production mode, you should use webpack production shortcut. Like this:
webpack -p
This will enable webpack optimize options to minify your JS. See more detailed explanation of webpack flags on this SO answer.
Webpack plugins need to be put under the plugins key in module.exports.
https://webpack.github.io/docs/using-plugins.html#built-in-plugins
Try this:
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify('production') }
}),
]
}
Had the same error so to fix it I did this:
package.json
"scripts": {
"build": "NODE_ENV=production webpack --progress --colors",
"start": "NODE_ENV=development webpack-dev-server --progress --colors"
}
webpack.config.js
const env = process.env.NODE_ENV
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(env)
})
]
}
It should work for sure.
Here I have some configuration that you can try to optimize your build.
This worked for me: run npm run build followed by npm install -g serve and serve -s build

webpack dev server ignoring scss changes

I managed to compress / compile my js and scss files with webpack. The scss file gets extracted by the 'extract-text-webpack-plugin' into an external css file. Here is the code:
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
require('es6-promise').polyfill();
module.exports = {
entry: ['./js/app'],
output: {
path: path.join(__dirname, 'js'),
publicPath: 'js',
filename: 'app.min.js'
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false,
},
}),
new webpack.optimize.OccurrenceOrderPlugin(),
new ExtractTextPlugin("../css/styles.min.css", {allChunks: false})
],
module: {
loaders: [{
test: /\.scss$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!sass-loader")
}]
}
}
When I run now "webpack-dev-server js/app.js" - it gets my changes in the js file itself (alert for example) but does not remark changes in the css file.
This is the app.js:
var $ = require('jquery');
require('../css/styles.scss');
alert('Hi');
I guess the problem is connected to the ExtractTextPlugin. Then again I have no clue how to workaround. Any tips or ideas?
Okay, I got that going. When starting the webpack-dev-server, I'm just asking if we are in production enviroment:
const live = process.env.NODE_ENV === "production";
if(live) {
...
} else {
...
}
If we are not in production, it misses the ExtractTextPlugin out.
Finally to deploy my changes I type:
NODE_ENV=production webpack -p
One can also use a npm script to shorten this.

Categories

Resources