问题描述
在同构反应应用程序中,我有 myModule
,它在节点和浏览器环境中的行为应该不同。我想在 package.json
中为 myModule
配置此分割点:
In isomorphic react app I have myModule
which should behave differently on node and browser environments. I would like configure this split point in package.json
for myModule
:
package.json
package.json
{
"private": true,
"name": "myModule",
"main": "./myModule.server.js",
"browser": "./myModule.client.js"
}
文件结构
file structure
├── myModule
│ ├── myModule.client.js
│ ├── myModule.server.js
│ └── package.json
│
├── browser.js
└── server.js
所以当我使用 myModule $ c时$ c>在节点我应该只获得
myModule.server.js
:
So when I use myModule
in node I should get only myModule.server.js
:
server.js
import myModule from './myModule';
myModule(); // invoke myModule.server.js
在浏览器方面仅使用构建捆绑包 myModule.client.js
:
browser.js
import myModule from './myModule';
myModule(); // invoke myModule.client.js
使用这种方法,但我无法弄清楚这是什么配置定义。
react-starter-kit uses this approach but I can't figure out where is this configuration defined.
-
package.json
是进行这种拆分的良好语义点。 - 客户端包只包含
myModule.client.js
。
package.json
is good semantic point to do this kind of splitting.- Client side bundle only contain
myModule.client.js
.
已知解决方案 - 不是我的答案
你可以拥有这种文件结构:
Known solution - not an answer for me
You can have this kind of file structure:
├── myModule
│ ├── myModule.client.js
│ ├── myModule.server.js
│ └── index.js <-- difference
│
├── browser.js
└── server.js
并且在 index.js
:
if (process.browser) { // this condition can be different but you get the point
module.exports = require('./myModule.client');
} else {
module.exports = require('./myModule.server');
}
这个问题的主要问题是客户端包包含很多heavy kB后端代码。
The main problem with this is that client bundle contains a lot of heavy kB backend code.
我包含我的 webpack.config.js
。奇怪的是,此配置始终指向浏览器和节点的 myModule.client.js
。
I include my webpack.config.js
. Strangely this config always point to myModule.client.js
for browser and node.
const webpack = require('webpack');
var path = require('path');
var fs = require('fs');
const DEBUG = !process.argv.includes('--release');
const VERBOSE = !process.argv.includes('--verbose');
const AUTOPREFIXER_BROWSERS = [
'Android 2.3',
'Android >= 4',
'Chrome >= 35',
'Firefox >= 31',
'Explorer >= 9',
'iOS >= 7',
'Opera >= 12',
'Safari >= 7.1',
];
let nodeModules = {};
fs.readdirSync('node_modules')
.filter(function(x) {
return ['.bin'].indexOf(x) === -1 ;
})
.forEach(function(mod) {
nodeModules[mod] = 'commonjs ' + mod;
});
let loaders = [
{
exclude: /node_modules/,
loader: 'babel'
},
{
test: [/\.scss$/,/\.css$/],
loaders: [
'isomorphic-style-loader',
`css-loader?${DEBUG ? 'sourceMap&' : 'minimize&'}modules&localIdentName=` +
`${DEBUG ? '[name]_[local]_[hash:base64:3]' : '[hash:base64:4]'}`,
'postcss-loader?parser=postcss-scss'
]
},
{
test: /\.(png|jpg|jpeg|gif|svg|woff|woff2)$/,
loader: 'url-loader',
query: {
name: DEBUG ? '[name].[ext]' : '[hash].[ext]',
limit: 10000,
},
},
{
test: /\.(eot|ttf|wav|mp3)$/,
loader: 'file-loader',
query: {
name: DEBUG ? '[name].[ext]' : '[hash].[ext]',
},
},
{
test: /\.json$/,
loader: 'json-loader',
},
];
const common = {
module: {
loaders
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
],
postcss: function plugins(bundler) {
var plugins = [
require('postcss-import')({ addDependencyTo: bundler }),
require('precss')(),
require('autoprefixer')({ browsers: AUTOPREFIXER_BROWSERS }),
];
return plugins;
},
resolve: {
root: path.resolve(__dirname, 'src'),
extensions: ['', '.js', '.jsx', '.json']
}
};
module.exports = [
Object.assign({} , common, { // client
entry: [
'babel-polyfill',
'./src/client.js'
],
output: {
path: __dirname + '/public/',
filename: 'bundle.js'
},
target: 'web',
node: {
fs: 'empty',
},
devtool: DEBUG ? 'cheap-module-eval-source-map' : false,
plugins: [
...common.plugins,
new webpack.DefinePlugin({'process.env.BROWSER': true }),
],
}),
Object.assign({} , common, { // server
entry: [
'babel-polyfill',
'./src/server.js'
],
output: {
path: __dirname + '',
filename: 'server.js'
},
target: 'node',
plugins: [
...common.plugins,
new webpack.DefinePlugin({'process.env.BROWSER': false }),
],
node: {
console: false,
global: false,
process: false,
Buffer: false,
__filename: false,
__dirname: false,
},
externals: nodeModules,
})
];
推荐答案
自问这个问题已经很久了。我只是想澄清之前的答案。
It has been a long time since this question was asked. I just want to clarify the previous answer.
这似乎是这个webpack heavyior没有记录,但是当目标是'node'时,webpack会自动进入'main'条目,当target为'web'时,webpack会自动进入'browser'。
It seems this webpack heavior is not documented, but webpack automatically takes 'main' entry when target is 'node' and takes 'browser' entry when target is 'web'.
这篇关于package.json中节点和浏览器的不同主要入口点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!