本文介绍了package.json中节点和浏览器的不同主要入口点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在同构反应应用程序中,我有 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 节点我应该只获得 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.


  1. package.json 是进行这种拆分的良好语义点。

  2. 客户端包只包含 myModule.client.js

  1. package.json is good semantic point to do this kind of splitting.
  2. 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中节点和浏览器的不同主要入口点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-27 03:17