I am trying to upgrade an old framework I built in javascript to es6/module standards and I have a lot of troubles.
One of my current problems is that due to server side rendering my modules are sometime loaded in the node environment and are trying to access the window, causing errors.
Is there a principled way to manage this ?
The main jQuery file has a nice failback if window is undefined and can load in node without a fuss. I am trying to implement this in web-pack by I am stumbling.
This is my current webpack config
// @flow
// import path from 'path'
import webpack from 'webpack'
const WDS_PORT = 7000
const PROD = JSON.parse(process.env.PROD_ENV || '0')
const libraryName = 'experiment'
const outputFile = `${libraryName}${PROD ? '.min' : '.max'}.js`
const plugins = [
new webpack.optimize.OccurrenceOrderPlugin(),
]
const prodPlugins = plugins.concat(new webpack.optimize.UglifyJsPlugin())
// not really working
export default {
entry: './builder.js',
target: 'web',
output: {
path: `${__dirname}/lib`,
filename: outputFile,
library: libraryName,
libraryTarget: 'umd',
umdNamedDefine: true,
},
module: {
loaders: [
{
test: /(\.jsx|\.js)$/,
loader: 'babel-loader',
exclude: /(node_modules|bower_components)/,
},
],
},
devtool: PROD ? false : 'source-map',
resolve: {
extensions: ['.js', '.jsx'],
},
externals: {
chartjs: {
commonjs: 'chartjs',
amd: 'chartjs',
root: 'Chart', // indicates global variable
},
lodash: {
commonjs: 'lodash',
amd: 'lodash',
root: '_', // indicates global variable
},
jquery: 'jQuery',
mathjs: {
commonjs: 'mathjs',
amd: 'mathjs',
root: 'math', // indicates global variable
},
'experiment-boxes': {
commonjs: 'experiment-boxes',
amd: 'experiment-boxes',
root: 'experimentBoxes', // indicates global variable
},
'experiment-babylon-js': {
commonjs: 'experiment-babylon-js',
amd: 'experiment-babylon-js',
root: 'EBJS', // indicates global variable
},
},
devServer: {
port: WDS_PORT,
hot: true,
},
plugins: PROD ? prodPlugins : plugins,
}
And this is my main entry point builder.js
/* --- Import the framwork --- */
import TaskObject from './src/framework/TaskObject'
import StateManager from './src/framework/StateManager'
import State from './src/framework/State'
import EventData from './src/framework/EventData'
import DataManager from './src/framework/DataManager'
import RessourceManager from './src/framework/RessourceManager'
import {
Array,
String,
diag,
rowSum,
getRow,
matrix,
samplePermutation,
rep,
Deferred,
recurse,
jitter,
delay,
looksLikeAPromise,
mustHaveConstructor,
mustBeDefined,
mandatory,
debuglog,
debugWarn,
debugError,
noop,
} from './src/framework/utilities'
/* add it to the global space in case user want to import in a script tag */
if (typeof window !== 'undefined') {
window.TaskObject = TaskObject
window.StateManager = StateManager
window.State = State
window.EventData = EventData
window.DataManager = DataManager
window.RessourceManager = RessourceManager
window.jitter = jitter
window.delay = delay
window.Deferred = Deferred
}
export {
TaskObject,
StateManager,
State,
EventData,
DataManager,
RessourceManager,
Array,
String,
diag,
rowSum,
getRow,
matrix,
samplePermutation,
rep,
Deferred,
recurse,
jitter,
delay,
looksLikeAPromise,
mustHaveConstructor,
mustBeDefined,
mandatory,
debuglog,
debugWarn,
debugError,
noop,
}
Am I on the right track?
Ok my solution so far, although feels like a hack, protects against require()
in node environment.
In the ENTRY FILE of your webpack config check for window
being defined.
Here is an example when trying to re-bundle babylonjs which relies heavily on window and would generate an error when required by node:
builder.js
let BABYLON = {}
let OIMO = {}
if (typeof window !== 'undefined') {
BABYLON = require('./src/babylon.2.5.full.max')
OIMO = require('./src/Oimo').OIMO
window.BABYLON = BABYLON
window.OIMO = OIMO
}
module.exports = { BABYLON, OIMO }
webpack.config.babel.js
import path from 'path'
import webpack from 'webpack'
const WDS_PORT = 7000
const PROD = JSON.parse(process.env.PROD_ENV || '0')
const plugins = [
new webpack.optimize.OccurrenceOrderPlugin(),
]
const prodPlugins = plugins.concat(new webpack.optimize.UglifyJsPlugin())
export default {
entry: [
'./builder.js',
],
output: {
filename: PROD ? 'babylon.min.js' : 'babylon.max.js',
path: path.resolve(__dirname, 'lib/'),
publicPath: `http://localhost:${WDS_PORT}/lib/`,
library: 'EBJS',
libraryTarget: 'umd',
umdNamedDefine: true,
},
module: {
rules: [
{ test: /\.(js|jsx)$/, use: 'babel-loader', exclude: /node_modules/ },
],
},
devtool: PROD ? false : 'source-map',
resolve: {
extensions: ['.js', '.jsx'],
},
devServer: {
port: WDS_PORT,
hot: true,
},
plugins: PROD ? prodPlugins : plugins,
}
Testing the bundle in node with a simple file like so:
bundle.test.js
const test = require('./lib/babylon.min.js')
console.log(test)
Will produce in the terminal:
$ node bundle.test.js
{ BABYLON: {}, OIMO: {} }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.