javascript – webpack split chunks将所有内容放在一个文件中

我有大量的应用程序,我想拆分它.

目前我有这样的结构:

application.js < entry point
Messages.js < application.js inner module
SystemSetup.js < application.js inner module
/node_modules/react.js < node modules
Common.js < local file, used inside of Messages and SystemSetup

有可能将它分成相同的块吗?我的意思是,我需要得到

Common.js < module(chunk) with no dependencies
node_module.js < module(chunk) without dependencies
Messages.js < depends from Common and node_modules
SystemSetup.js < depends from Common and node_modules
application.js < depends from Messages and SystemSetup

目前我制作了这个webpack配置文件:

const path = require('path');
const WebpackNotifierPlugin = require('webpack-notifier');
const AsyncChunkNames = require('webpack-async-chunk-names-plugin');
const Profile = require('./src/js/Profile');
const production = Profile.environment === 'prod';

module.exports = {
    mode: production ? 'production' : 'development',
    entry: {
        application: './src/js/Application.js',
        Messages: './src/js/components/routes/Messages.js',
        SystemSetup: './src/js/components/routes/SystemSetup.js'
    },
    output: {
        path: path.resolve(__dirname, '../assets/js/'),
        filename: '[name].js',
        chunkFilename: '[name].js',
        publicPath: "/"
    },
    cache: true,
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: ['babel-loader']
            }
        ]
    },
    watchOptions: {
        ignored: /node_modules/
    },
    plugins: [
        new WebpackNotifierPlugin({alwaysNotify: true, title: 'Webpack JS job'}),
        new AsyncChunkNames()
    ],
    devtool: 'source-map',
    resolve: {
        alias: {
            root: path.join(__dirname, 'src/js/'),
            '~': path.resolve(__dirname, 'src/js/'),
        }
    },
    optimization: {
        splitChunks: production ? {} : {
            cacheGroups: {
                default: false,
                vendors: false,
                node_modules: {
                    name: 'node_modules',
                    chunks: 'all',
                    test: /node_modules/,
                    priority: 40
                },
                common: {
                    name: 'common',
                    minChunks: 2,
                    chunks: 'all',
                    priority: 20,
                    reuseExistingChunk: true,
                    enforce: true
                },
                Messages: {
                    name: 'Messages',
                    chunks: 'all',
                    test: /.*\/Messages\.js$/,
                    reuseExistingChunk: true,
                    priority: 30
                },
                SystemSetup: {
                    name: 'SystemSetup',
                    chunks: 'all',
                    test: /.*\/SystemSetup\.js$/,
                    reuseExistingChunk: true,
                    priority: 30
                },
            }
        }
    }
};

我得到了所有捆绑 – 但结果并不好.我有这样的文件:

Common.js < 11mb files, expected around 5mb
node_module.js < 3.7 mb < looks good
Messages.js < 7kb, expected around 3mb
SystemSetup.js < 7kb, expected around 3mb
application.js < 7kb < looks good

最佳答案 首先,让我清楚地说明如何使用现代方法将Webpack与使用ES6模块进行Javascript捆绑[ES2015].

>当前JS模块格式(CommonJS,AMD)和ES6模块之间最重要的区别在于ES6模块在设计时考虑了静态分析.
>这意味着在导入模块时,导入将在编译时解析,即在脚本开始执行之前.
>这允许我们在运行程序之前删除其他模块未使用的导出.
>删除未使用的导出可以节省大量空间,减轻浏览器的压力.

当你使用像UglifyJS这样的东西来缩小你的代码时,这与死代码消除有何不同?

答案是,这取决于.死代码消除是一个优化步骤,可以删除未使用的代码,并将变量视为删除捆绑的程序在捆绑后不需要运行的多余行李.

有时,死代码消除可以在UglifyJS和ES6模块之间完全相同,有时则不行.

JavaScript捆绑Webpack的现代方法

Webpack是一种现代静态文件捆绑工具.在JavaScript文件捆绑的情况下,它有助于消除标记中对已排序标记的隐式依赖性.我们不是包含许多单独的脚本,而是包含使用相同标记的单个或几个包.

为此,我们应该首先创建这些包.要创建bundle,我们需要配置Webpack.当然,Webpack应该安装在机器上,例如通过命令npm install webpack –save-dev.

在它最基本的Webpack需要的是一个入口点和输出.然后可以通过执行命令简单地调用它.

./node_modules/.bin/webpack app/entry.js dist/output.js

在这种情况下,Webpack将加载entry.js并将在其中查找import或require关键字以确定是否应加载更多依赖项.如果找到依赖项,它将以递归方式加载它们,并将它们包含在输出文件中

JavaScript模块

如前一节所述,脚本文件可以包含import或require引用的依赖项.

// CommonJS
require ('lodash')
console.log(_);
// ECMA6
import 'lodash'
console.log(_);
// Notice currently you need to transpile ECMA6 import using for example Babel to make it run in browsers

这只是为了指出一个人可以使用JavaScript文件中引用依赖项的功能.使用默认的Webpack配置,它将捆绑一个与当前浏览器不兼容的输出脚本.并且如评论中所述,我们需要处理包含导入或要求的脚本文件.这可以使用Babel JavaScript转换器完成,其任务是使用ECMA6编写的JavaScript并将其转换为工作的ECMA5 JavaScript.您可以在Mozilla Developer Network上找到有关JavaScript importexport的更多信息.

捆绑JavaScript Webpack方式

您可以通过提供条目文件和输出路径,使用CLI命令捆绑JavaScript. Webpack将自动解决import和require中的所有依赖项.并将它们与您的应用程序脚本一起捆绑到单个输出中.

但这只是它能做的最低限度.为了扩展功能,我们可以创建Webpack的配置文件,并配置捆绑器在处理JavaScript时执行的各种任务.

组态

首先,我们需要创建一个webpack.config.js文件,并需要来自node_modules的webpack.

// webpack.config.js
var webpack = require('webpack');
module.exports = {
    entry: {
        entry: __dirname + '/entry.js'
    },
    output: {
        filename: '[name].bundle.js'
    }
}

这里我们提供了条目文件作为entry.js,并为执行Webpack的当前目录的路径添加了前缀.还提供了输出路径,用于放置捆绑JavaScript的内容.注意文件的[name]前缀.这指示Webpack将条目文件名与.bundle.js结尾连接起来.现在执行CLI命令.

./node_modules/.bin/webpack

它将在当前模块的目录中创建一个entry.bundle.js文件.

装载机

正如我之前所写,如果您使用import来引用脚本中的JavaScript依赖项,则必须使用Babel将其从ECMA6转换为ECMA5脚本. Webpack可以通过利用它的加载器功能实现这一点.为了使它工作,我们必须首先安装必要的节点模块npm install babel-core babel-loader babel-preset-es2015并使用modules部分更新webpack.config.js.

// webpack.config.js
var webpack = require('webpack')
module.exports = {
    entry: {
        entry: __dirname + '/entry.js'
    },
    output: {
        filename: '[name].bundle.js'
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/,
                query: {
                    presets: ['es2015']
                }
            }
        ]
    },
}

在模块部分,我们可以设置许多在处理时应用于JavaScript的加载器.请注意,我们已设置所有以* .js结尾的文件(不包括node_modules)应通过babel-loader处理.因此,它将生成ECMA5兼容代码作为输出.所以现在如果我们在entry.js中添加例如对helloWorld.js的依赖,Webpack就能生成工作代码.

// helloWorld.js
export const helloWorld = 'Hello world from imported JS!';
// entry.js
import {helloWorld} from './helloWorld'
console.log(helloWorld); // Will print 'Hello world from imported JS!' in browser's console

插件

所以我们已经看到了入口,输出和模块配置的实际应用.但是还有一个基本配置部分值得一看.这是插件.简单地说,插件与捆绑JavaScript相同,因为加载器与单个JavaScript依赖关系相同.插件允许我们在捆绑包上执行各种任务.例如,将重复的代码块提取到单独的文件中或者对输出进行uglify.

// webpack.config.js
var webpack = require('webpack')
module.exports = {
    entry: {
        entry: __dirname + '/entry.js'
    },
    output: {
        filename: '[name].bundle.js'
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/,
                query: {
                    presets: ['es2015']
                }
            }
        ]
    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin()
    ]
}

如您所见,我们在Webpack配置插件中添加了一个新部分.它可以包含许多要在捆绑的JavaScript上执行的插件. Webpack本身提供了一个有用的plugins列表.但您也可以根据具体原因构建自己的列表.

优点

>更多地控制依赖关系,因为视图仅导入需要工作的脚本.
>使用现代JavaScript(ES6功能).
> Webpack可以在编译时分析JavaScript的内容.从而为优化提供更多信息.
>引用类与在C#或PHP中执行类似.

缺点

>当框架中存在功能时,需要安装额外的工具.
>开发人员必须在配置中定义所有入口点(每页或每个视图一个).
> JavaScript必须是应用程序和第三方的模块化.

(要么)

如果你只想用webpack拆分你的块:The 100% correct way to split your chunks with Webpack

点赞