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\"
Related
First the code, it's a pretty silly example but it's pulled out from a more complicated github action:
index.js
require('#octokit/rest');
console.log('hello world');
webpack.config.js
const path = require('path');
module.exports = {
target: 'node',
entry: './index.js',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
},
};
package.json
{
"private": true,
"devDependencies": {
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10"
},
"dependencies": {
"#octokit/rest": "^16.35.0"
}
}
build command
node_modules/.bin/webpack --config webpack.config.js
running without webpack
$ node index.js
hello world
running after building webpack
$ node dist/index.js
/tmp/x/dist/index.js:1
...
ReferenceError: navigator is not defined
at Module.i (/tmp/x/dist/index.js:1:3659)
at Object.<anonymous> (/tmp/x/dist/index.js:15:6701)
at t (/tmp/x/dist/index.js:1:110)
at Object.<anonymous> (/tmp/x/dist/index.js:15:874)
at t (/tmp/x/dist/index.js:1:110)
at Object.<anonymous> (/tmp/x/dist/index.js:15:697)
at t (/tmp/x/dist/index.js:1:110)
at Object.<anonymous> (/tmp/x/dist/index.js:1:3891)
at t (/tmp/x/dist/index.js:1:110)
at Object.<anonymous> (/tmp/x/dist/index.js:15:418)
analysis
From what I've found, there's a compiled typescript package inside node_modules that's being imported and run here, here's some of the relevant code from the last two frames:
node_modules/#octokit/endpoint/dist-src/defaults.js
// ...
import { getUserAgent } from "universal-user-agent";
// ...
const userAgent = `octokit-endpoint.js/${VERSION} ${getUserAgent()}`;
// ...
The universal-user-agent provides several implementations of its code in the following files:
node_modules/universal-user-agent/dist-node/index.js
node_modules/universal-user-agent/dist-web/index.js
As you would expect, the dist-web implementation uses navigator.userAgent -- the node one does something else.
my current terrible workaround
I don't actually care about the user agent so I'm currently hacking around this with:
sed -i 's/\bnavigator\b/({})/g' dist/index.js
yes, running sed to eliminate accesses to navigator
tl;dr
How do I convince webpack to pick the dist-node implementation over the dist-web one (like require(...) seems to do when running node directly)?
It's a known issue for #octokit/rest: https://github.com/octokit/rest.js/issues/1485
There is also a long discussion in this universal-user-agent issue: https://github.com/gr2m/universal-user-agent/issues/23
There seems to be a permanent fix, but not released yet. Until then you can try 2 things to resolve the dist-node of universal-user-agent using Webpack Resolve:
1) Using alias to resolve the dist-node
const path = require('path');
module.exports = {
target: 'node',
resolve: {
alias: {
'universal-user-agent': path.resolve(__dirname, 'node_modules/universal-user-agent/dist-node/index.js')
}
},
entry: './index.js',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
},
};
2) Using mainFields
module.exports = {
target: 'node',
resolve: {
mainFields: ['main', 'module']
},
entry: './index.js',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
},
};
You should go with the first method, because the second one reflects to all node_modules and you'll run into issues sooner or later.
Webpack issue
There seems to be an issue and a long discussion about this problem here: https://github.com/webpack/webpack/issues/5756
I have a rather large React application built with webpack 2. The application is embedded into a Drupal site as a SPA within the existing site. The Drupal site has a complex gulp build setup and I can't replicate it with webpack, so I decided to keep it.
I have split my React application into multiple parts using the DllPlugin / DllReferencePlugin combo which is shipped out of the box in webpack 2. This works great, and I get a nice vendor-bundle when building with webpack.
The problem is when I try to run my webpack configuration in gulp, I get an error. I might be doing it wrong, as I have not been able to find much documentation on this approach, but nevertheless, it's not working for me.
It looks like it's trying to include the the manifest file from my vendor-bundle before creating it.
Whenever I run one of my defined gulp tasks, like gulp react-vendor I get an error, saying that it cannot resolve the vendor-manifest.json file.
If I on other hand run webpack --config=webpack.dll.js in my terminal, webpack compiles just fine and with no errors.
I have included what I think is the relevant files. Any help on this is appreciated.
webpack.config.js
// Use node.js built-in path module to avoid path issues across platforms.
const path = require('path');
const webpack = require('webpack');
// Set environment variable.
const production = process.env.NODE_ENV === "production";
const appSource = path.join(__dirname, 'react/src/');
const buildPath = path.join(__dirname, 'react/build/');
const ReactConfig = {
entry: [
'./react/src/index.jsx'
],
output: {
path: buildPath,
publicPath: buildPath,
filename: 'app.js'
},
module: {
rules: [
{
exclude: /(node_modules)/,
use: {
loader: "babel-loader?cacheDirectory=true",
options: {
presets: ["react", "es2015", "stage-0"]
},
},
},
],
},
resolve: {
modules: [
path.join(__dirname, 'node_modules'),
'./react/src/'
],
extensions: ['.js', '.jsx', '.es6'],
},
context: __dirname,
devServer: {
historyApiFallback: true,
contentBase: appSource
},
// TODO: Split plugins based on prod and dev builds.
plugins: [
new webpack.DllReferencePlugin({
context: path.join(__dirname, "react", "src"),
manifest: require(path.join(__dirname, "react", "vendors", "vendor-manifest.json"))
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
filename: 'webpack-loader.js'
}),
]
};
// Add environment specific configuration.
if (production) {
ReactConfig.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
module.exports = [ReactConfig];
webpack.dll.js
const path = require("path");
const webpack = require("webpack");
const production = process.env.NODE_ENV === "production";
const DllConfig = {
entry: {
vendor: [path.join(__dirname, "react", "vendors", "vendors.js")]
},
output: {
path: path.join(__dirname, "react", "vendors"),
filename: "dll.[name].js",
library: "[name]"
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, "react", "vendors", "[name]-manifest.json"),
name: "[name]",
context: path.resolve(__dirname, "react", "src")
}),
// Resolve warning message related to the 'fetch' node_module.
new webpack.IgnorePlugin(/\/iconv-loader$/),
],
resolve: {
modules: [
path.join(__dirname, 'node_modules'),
],
extensions: ['.js', '.jsx', '.es6'],
},
// Added to resolve a dependency issue in this build #https://github.com/hapijs/joi/issues/665
node: {
net: 'empty',
tls: 'empty',
dns: 'empty'
}
};
if (production) {
DllConfig.plugins.push(
new webpack.optimize.UglifyJsPlugin()
);
}
module.exports = [DllConfig];
vendors.js (to determine what to add to the Dll)
require("react");
require("react-bootstrap");
require("react-dom");
require("react-redux");
require("react-router-dom");
require("redux");
require("redux-form");
require("redux-promise");
require("redux-thunk");
require("classnames");
require("whatwg-fetch");
require("fetch");
require("prop-types");
require("url");
require("validator");
gulpfile.js
'use strict';
const gulp = require('gulp');
const webpack = require ('webpack');
const reactConfig = require('./webpack.config.js');
const vendorConfig = require('./webpack.dll.js');
// React webpack source build.
gulp.task('react-src', function (callback) {
webpack(reactConfig, function (err, stats) {
callback();
})
});
// React webpack vendor build.
gulp.task('react-vendor', function (callback) {
webpack(vendorConfig, function (err, stats) {
callback();
})
});
// Full webpack react build.
gulp.task('react-full', ['react-vendor', 'react-src']);
NOTE:
If I build my vendor-bundle with the terminal with webpack --config=webpack.dll.js first and it creates the vendor-manifest.json file, I can then subsequently successfully run my gulp tasks with no issues.
This is not very helpful though, as this still will not allow me to use webpack with gulp, as I intend to clean the build before new builds run.
I ended up using the solution mentioned in the end of my question. I build my DLL file first and then I can successfully run my gulp webpack tasks.
One change that can make it easier to debug the issue, is to use the Gulp utility module (gulp-util) to show any webpack errors that might show up during build of webpack, using gulp.
My final gulp setup ended up looking like this:
gulpfile.js
'use strict';
const gulp = require('gulp');
const gutil = require('gulp-util');
const webpack = require('webpack');
const reactConfig = require('./webpack.config.js');
const vendorConfig = require('./webpack.dll.js');
// React webpack source build.
gulp.task('react', function (callback) {
webpack(reactConfig, function (err, stats) {
if (err) {
throw new gutil.PluginError('webpack', err);
}
else {
gutil.log('[webpack]', stats.toString());
}
callback();
});
});
// React webpack vendor build.
gulp.task('react-vendor', function (callback) {
webpack(vendorConfig, function (err, stats) {
if (err) {
throw new gutil.PluginError('webpack', err);
}
else {
gutil.log('[webpack]', stats.toString());
}
callback();
});
});
// React: Rebuilds both source and vendor in the right order.
gulp.task('react-full', ['react-vendor'], function () {
gulp.start('react');
});
I hope this might help someone in a similar situation.
Whenever I run one of my defined gulp tasks, like gulp react-vendor I get an error, saying that it cannot resolve the vendor-manifest.json file.
Your gulpfile.js contains this:
const reactConfig = require('./webpack.config.js');
const vendorConfig = require('./webpack.dll.js');
And webpack.config.js contains this:
new webpack.DllReferencePlugin({
context: path.join(__dirname, "react", "src"),
manifest: require(path.join(__dirname, "react", "vendors", "vendor-manifest.json"))
}),
The require() calls are currently all executed immediately. Whenever you run Gulp, it will evaluate both Webpack configuration files. As currently configured, Node runs the code in webpack.config.js at startup, and from there it sees the require() used in your creation of the DllReferencePlugin, so it will also try to read manifest.json at that time and turn it into an object...which is before it has been built.
You can solve this in one of two ways:
The DllReferencePlugin's manifest option supports either an object (which is what you are currently providing), or else a string containing the path of the manifest file. In other words, it should work if you remove the require() from around your path.join(...) call.
Alternatively, you can also defer the loading of the Webpack config files. Moving your const reactConfig = require('./webpack.config.js'); from the top of the file directly into the gulp task function should be sufficient, assuming that this function is not invoked until after the manifest has been built.
i want to provide a webpack bundle which contains all common thirdparty vendors(angular 1.4, jQuery, and some other libs).
Currently the follow modules are developed
Module A
Vendor Module
Vendor Module:
Create a simple module with all thridparty libs(angular 1.4, jQuery, and some other libs)
webpack.config.js:
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: {
vendor: './index.js',
},
output: {
// filename: '[chunkhash].[name].js',
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
plugins: []
}
index.js:
require('jquery');
require('angular');
Module A:
index.js:
var angular = require('angular');
var myJQ = require('jQuery');
var app = angular.module("Test", []);
console.log("Angular Boostrap");
console.log(app);
console.log("jQuery Boostrap");
console.log(myJQ);
webpack.config.js:
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: {
main: './index.js',
},
externals: {
angular: 'angular',
"jQuery": {
root: '$',
commonjs: 'jquery',
amd: 'jquery'
}
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
plugins: []
}
Module A index.js can require 'angular' and i see the right output, but the require from 'jquery' failed with an error.
There a two questions in my mind.
Which is common way to include third party vendors?
Whats wrong with jquery in the Module A index.js
Thank you.
The best way to include third party vendors is the DllPlugin. It does exactly what you want, splitting your app in two bundles. That way the build process is fast, independent and you have no limits in your app, because the dllPlugin connects both bundles. Sadly, there is no documentation about the dllPlugin in the webpack v2 documentation yet, but there are tutorials around, like https://robertknight.me.uk/posts/webpack-dll-plugins/
I think it depends on which jQuery you use. If jQuery exposes itself onto the window automatically, try
externals: { jQuery: 'window.jQuery' }
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 () {}
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.