我有大量的应用程序,我想拆分它.
目前我有这样的结构:
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 import和export的更多信息.
捆绑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