Webpack babel配置服务器和客户端javascript? [英] Webpack babel config for both server and client javascript?

查看:101
本文介绍了Webpack babel配置服务器和客户端javascript?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在试图找出如何使用单个webpack配置文件,该文件适用于使用es2015预设转换服务器(node.js)js和客户端js。目前,我必须专门设置target:'node'才能正确处理基于节点的文件。如果我不这样做,那么webpack会根据默认的target:'web'进行转换。然后报告错误,因为明确导入的'mysql'模块不适用于web。

I'm trying to figure out how to have a single webpack config file that works for transforming both server (node.js) js and client js with the es2015 preset. Currently I have to specifically set "target: 'node'" for it to correctly process node-based files. If I don't, then webpack does the transformation based on the default "target: 'web'". It then reports errors because the 'mysql' module being imported clearly won't work for web.

如何将两者统一到同一个配置文件中,以便服务器和客户端js会单独转换吗?或者我是否需要完全单独的配置?

How can I unify both into the same config file so that server and client js will be transformed separately? Or do I need separate configs entirely?

示例webpack.config.js

Sample webpack.config.js

'use strict';

var path = require('path');
var webpack = require('webpack');

module.exports = {
  target: 'node',
  resolve: {
    root: path.resolve(__dirname),
    extensions: ['', '.js']
  },
  entry: [
    'babel-polyfill',
    './index.js',
  ],
  output: {
    filename: 'bundle.js'       
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          presets: ['es2015']
        }
      }
    ]
  }
};

示例js代码

import 'babel-polyfill';
import mysql from 'mysql';

class Test {
  constructor () {

  }

  get read () {

  }
};


推荐答案

你可以为Webpack传递多个配置来处理同时。只需返回一组配置对象。

You can pass multiple configs for Webpack to process at the same time. Simply return an array of configuration objects.

export default [
  { 
    // config 1 here
  },
  {
    // config 2 here
  },
];

额外提示:如果您使用 .babel.js 作为配置文件的扩展名,Webpack将为您运行Babel,允许您在Webpack配置中使用ES6。

Extra tip: if you use .babel.js as extension for your config file, Webpack will run it through Babel for you, which allows you to use ES6 in your Webpack config.

Bonus:下面的代码段

Bonus: the snippet below

// Source: https://gist.github.com/Ambroos/f23d517a4261e52b4591224b4c8df826

import webpack from 'webpack';
import path from 'path';

import CleanPlugin from 'clean-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import AssetsPlugin from 'assets-webpack-plugin';
import CompressionPlugin from 'compression-webpack-plugin';
import autoprefixer from 'autoprefixer';
import rucksack from 'rucksack-css';
import cssnano from 'cssnano';
import moment from 'moment';

const sharedPlugins = [
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /nl/),
    new webpack.optimize.AggressiveMergingPlugin({}),
    new webpack.optimize.OccurenceOrderPlugin(true),
    new webpack.optimize.UglifyJsPlugin({
        compress: {
            drop_console: true,
            screw_ie8: true,
            sequences: true,
            properties: true,
            dead_code: true,
            drop_debugger: true,
            conditionals: true,
            comparisons: true,
            evaluate: true,
            booleans: true,
            loops: true,
            unused: true,
            if_return: true,
            join_vars: true,
            cascade: true,
            negate_iife: true,
            hoist_funs: true,
            warnings: false,
        },
        mangle: {
            screw_ie8: true,
        },
        output: {
            screw_ie8: true,
            preamble: '/* Website - ' + moment().format() + ' */',
        },
    }),
];

const sharedServerPlugins = [
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /nl/),
    new webpack.optimize.AggressiveMergingPlugin({}),
    new webpack.optimize.OccurenceOrderPlugin(true),
    new webpack.optimize.UglifyJsPlugin({
        compress: {
            drop_console: false,
            screw_ie8: true,
            sequences: true,
            properties: true,
            dead_code: true,
            drop_debugger: false,
            conditionals: true,
            comparisons: true,
            evaluate: true,
            booleans: true,
            loops: true,
            unused: true,
            if_return: true,
            join_vars: true,
            cascade: true,
            negate_iife: true,
            hoist_funs: true,
            warnings: false,
        },
        mangle: {
            screw_ie8: true,
        },
        output: {
            screw_ie8: true,
            preamble: '/* Website - ' + moment().format() + ' */',
        },
    }),
];

const PATHS = {
    build: path.resolve(__dirname, '..', 'build'),
    sourcemaps: path.resolve(__dirname, '..', 'build', 'sourcemaps'),
    browserSource: path.resolve(__dirname, '..', 'src', 'browser', 'index.js'),
    browserBuild: path.resolve(__dirname, '..', 'build', 'browser'),
    serverSource: path.resolve(__dirname, '..', 'src', 'server', 'index.js'),
    serverAssetsSource: path.resolve(__dirname, '..', 'src', 'server', 'assets', 'index.js'),
    serverBuild: path.resolve(__dirname, '..', 'build', 'server'),
};

export default [
    // Browser
    {
        entry: { browser: PATHS.browserSource },
        output: {
            path: PATHS.browserBuild,
            filename: 's/[chunkhash].js',
            chunkFilename: 's/async-[chunkhash].js',
            publicPath: '/',
            sourceMapFilename: '../sourcemaps/browser/[file].map',
        },
        devtool: 'hidden-source-map',
        plugins: [
            new AssetsPlugin({
                prettyPrint: true,
                path: path.resolve(PATHS.build, 'browserAssets'),
                filename: 'index.js',
                processOutput: assets => `module.exports = ${JSON.stringify(assets, null, '    ')};`,
            }),
            new CleanPlugin([PATHS.browserBuild, PATHS.sourcemaps], path.resolve(PATHS.build, 'browserAssets')),
            new ExtractTextPlugin('s/[contenthash].css'),
            new CompressionPlugin({
                asset: '{file}.gz',
                algorithm: 'gzip',
                regExp: /\.js$|\.html$|\.css$|\.svg$|\.eot$|\.xml$/,
                threshold: 1400,
                minRation: 0.8,
            }),
            new webpack.DefinePlugin({
                'process.env': {
                    NODE_ENV: JSON.stringify('production'),
                    WEBPACK_ENV: JSON.stringify('browser'),
                    APP_ENV: (process.env.APP_ENV && JSON.stringify(process.env.APP_ENV)) || undefined,
                },
            }),
        ].concat(sharedPlugins),
        externals: [
            { browserConfig: 'var websiteBrowserConfig' },
            { programs: 'var programs' },
        ],
        module: {
            loaders: [
                {
                    test: /\.jsx?$/,
                    exclude: /node_modules/,
                    loader: 'babel',
                },
                {
                    test: /\.json$/,
                    loader: 'json',
                },
                {
                    test: /\.scss$/,
                    loader: ExtractTextPlugin.extract(
                        'style',
                        [
                            'css?importLoaders=2&localIdentName=css-module-[hash:base64]',
                            'postcss',
                            'sass',
                        ]
                    ),
                },
                {
                    test: /\.(gif|png|jpe?g|svg|ico)$/i,
                    loaders: [
                        'url?limit=1400&name=s/i/[sha512:hash:base64:16].[ext]',
                        'image-webpack?bypassOnDebug',
                    ],
                },
                {
                    test: /isotope\-|fizzy\-ui\-utils|desandro\-|masonry|outlayer|get\-size|doc\-ready|eventie|eventemitter/,
                    loader: 'imports?define=>false&this=>window',
                },
                {
                    test: /flickity/,
                    loader: 'imports?define=>false&this=>window',
                },
                {
                    test: /node_modules\/unipointer/,
                    loader: 'imports?define=>undefined',
                },
            ],
        },
        postcss: () => {
            return [rucksack, autoprefixer, cssnano];
        },
    },

    // Server assets
    {
        entry: { assets: PATHS.serverAssetsSource },
        target: 'node',
        output: {
            path: PATHS.browserBuild,
            libraryTarget: 'commonjs',
            filename: '../serverAssets/index.js',
            publicPath: '/',
        },
        plugins: [
            // assetsWriter,
            new CompressionPlugin({
                asset: '{file}.gz',
                algorithm: 'gzip',
                regExp: /\.js$|\.html$|\.css$|\.svg$|\.eot$|\.xml$/,
                threshold: 1400,
                minRation: 0.8,
            }),
            new webpack.DefinePlugin({
                'process.env': {
                    NODE_ENV: JSON.stringify('production'),
                    WEBPACK_ENV: JSON.stringify('assets'),
                    APP_ENV: (process.env.APP_ENV && JSON.stringify(process.env.APP_ENV)) || undefined,
                },
            }),
        ].concat(sharedPlugins),
        module: {
            loaders: [
                {
                    test: /\.jsx?$/,
                    exclude: /node_modules/,
                    loader: 'babel',
                },
                {
                    test: /\.json$/,
                    loader: 'json',
                },
                {
                    test: /\.(gif|png|jpe?g|svg|ico)$/i,
                    loaders: [
                        'url?limit=1400&name=s/i/[sha512:hash:base64:16].[ext]',
                        'image-webpack?bypassOnDebug',
                    ],
                },
            ],
        },
    },

    // Server
    {
        entry: PATHS.serverSource,
        target: 'node',
        output: {
            path: PATHS.build,
            libraryTarget: 'commonjs',
            filename: 'server/server.js',
            publicPath: '/s/',
            sourceMapFilename: 'sourcemaps/browser/[file].map',
        },
        externals: [
            { serverAssets: '../serverAssets/index.js' },
            { browserAssets: '../browserAssets/index.js' },
            { vrtConfig: '../../env_vars.js' },
            /^(?!\.|\/).+/i,
            /webpack-assets\.json/,
        ],
        plugins: [
            new CleanPlugin(PATHS.serverBuild),
            new webpack.DefinePlugin({
                'process.env': {
                    NODE_ENV: JSON.stringify('production'),
                    WEBPACK_ENV: JSON.stringify('server'),
                    APP_ENV: (process.env.APP_ENV && JSON.stringify(process.env.APP_ENV)) || undefined,
                },
            }),
        ].concat(sharedServerPlugins),
        node: {
            __dirname: false,
            __filename: false,
        },
        module: {
            loaders: [
                {
                    test: /\.jsx?$/,
                    exclude: /node_modules/,
                    loader: 'babel',
                },
                {
                    test: /\.json$/,
                    loader: 'json',
                },
            ],
        },
    },
];

这是我们在我们的某个站点中使用的配置,它具有部分共享的代码库和部分共享资源。它由三个Webpack构建于一个:

That is the config we use in one of our sites with a partially shared codebase, and partially shared assets. It consists of three Webpack builds in one:


  • 浏览器

  • 服务器资产(图像/字体/ ...将在服务器生成的HTML中引用)

  • 服务器代码(节点)

服务器代码有一些特殊属性:

The server code has a few special properties:


  • target:'node'(Webpack需要这个)

  • output.libraryTarget:'commonjs'(使Webpack对非捆绑的库使用commonjs)

  • externals:[/^(?! \。|\/)。+ / i,] (使得Webpack不会在node_modules中捆绑任何内容,或任何不是相对路径的东西(以 / 开头)

  • target: 'node' (Webpack needs this)
  • output.libraryTarget: 'commonjs' (makes Webpack use commonjs for unbundled libs)
  • externals: [ /^(?!\.|\/).+/i, ] (makes Webpack not bundle anything in node_modules, or anything that is not a relative path (starting with . or /)

这个组合使得Webpack只处理你自己的代码,并通过require访问其他模块和库。这意味着使用本机绑定的依赖关系不会因为它们不会破坏捆绑。

This combination makes Webpack only process your own code, and access other modules and libraries through require. Which means your dependencies using native bindings won't break as they won't be bundled.

这篇关于Webpack babel配置服务器和客户端javascript?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆