Кажется, что в Интернете существует большой вакуум, когда дело доходит до разделения кода Angular с помощью Webpack 4 ( SplitChunksPlugin ).
Я прочитал почти все ресурсы на первой и второй страницах поисковой системы "разбивка кода по углам", в которую входят учебники по реагированию.Однако я не могу понять суть этого, поскольку существует множество противоречивых подходов.
У меня есть структура приложения, подобная этой:
app/
modules/
...
...
name/
- name.component.ts
- name.component.html
- name.module.ts
- name.service.ts
app.module.ts
app-routing.module.ts
main.ts
app.component.ts
app.js
webpack.config.js
Я уже загрузил все свои модули с отложенной загрузкой.Теперь я хочу разделить код как самого модуля (компонента, его зависимостей и т. Д.).
Что меня смущает, так это «как мне загрузить эти зависимости динамически?»
Я используюHtmlWebpackPlugin
для динамического добавления сгенерированного JavaScript в мой файл index.html.
Index.html
:
<body>
<!-- outlet! -->
<my-app></my-app>
</body>
После того, как HtmlWebpackPlugin
сгенерировал файлы javascript:
<body>
<!-- outlet! -->
<my-app></my-app>
<script type="text/javascript" src="/dist/main.bundle.js?7e402ab94c22169960b7"></script>
<script type="text/javascript" src="/dist/vendor.bundle.js?7e402ab94c22169960b7"></script>
</body>
main.bundle.js
- это мой код проекта, в то время как vendor.bundle.js
- это node_modules и т. Д.
Однако это довольно большой проект, ~ 23 МБ начальной загрузки страницы (да, 23 ...) Именно поэтому мне нужно для разделения кода этого проекта.
Мой первый вопрос : поскольку все ( поставщик и основной комплект *)1038 *) уже загружен в index.html (, в котором находится мой маршрутизатор-розетка ).Как мне код-разделить мои зависимости от моих компонентов?В любом случае, они все окажутся в Index.html, так как ... вот где находится роутер?Таким образом, не имеет значения, на сколько частей я делю свой js-код с моим текущим подходом.
webpack.config.js
:
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const sourcePath = path.join(__dirname, './public');
const destPath = path.join(__dirname, './public/dist');
const nodeModulesPath = path.join(__dirname, './node_modules');
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = function (env) {
const nodeEnv = env && env.prod ? 'production' : 'development';
const isProd = nodeEnv === 'production';
const plugins = [
new webpack.EnvironmentPlugin({
NODE_ENV: nodeEnv,
}),
// new BundleAnalyzerPlugin(),
new webpack.NamedModulesPlugin(),
new webpack.IgnorePlugin(/\.\/locale$/),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
Popper: ['popper.js', 'default']
}),
new HtmlWebpackPlugin({
hash: true,
template: sourcePath + '/index.html',
filename: sourcePath + '/dist/index.html'
})
];
if (isProd) {
plugins.push(
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
screw_ie8: true,
conditionals: true,
unused: true,
comparisons: true,
sequences: true,
dead_code: true,
evaluate: true,
if_return: true,
join_vars: true,
},
output: {
comments: false,
},
})
);
}
return {
mode: 'development',
devtool: isProd ? 'source-map' : 'eval',
context: nodeModulesPath,
entry: {
main: sourcePath + '/main.ts',
vendor: [
'bootstrap/dist/css/bootstrap.min.css',
'bootstrap/dist/js/bootstrap.min.js',
'moment/min/moment-with-locales.js',
'js-cookie/src/js.cookie.js',
'lodash/lodash.js',
'font-awesome/css/font-awesome.css',
'@fortawesome/fontawesome-free/css/all.css',
'admin-lte/dist/css/AdminLTE.css',
'admin-lte/dist/css/skins/skin-blue.css'
]
},
optimization: {
splitChunks: {
chunks: 'async',
minSize: 30000,
maxSize: 0,
minChunks: 2,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: 10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
},
output: {
path: destPath,
filename: '[name].bundle.js',
chunkFilename: '[name]-chunk.js',
publicPath: '/dist/'
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [{
loader: 'ts-loader',
options: {
transpileOnly: true // https://github.com/TypeStrong/ts-loader#faster-builds
}
}
],
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(png|gif|jpg|woff|woff2|eot|ttf|svg)$/,
loader: 'url-loader?limit=100000'
},
{
test: require.resolve('jquery'),
use: [
{ loader: 'expose-loader', options: 'jQuery' },
{ loader: 'expose-loader', options: '$' }
]
}
],
},
resolve: {
extensions: ['.js', '.ts'],
modules: [
path.resolve(__dirname, 'node_modules'),
],
alias: {
}
},
plugins: plugins,
performance: isProd && {
maxAssetSize: 100,
maxEntrypointSize: 300,
hints: 'warning',
},
stats: {
warnings: false,
colors: {
green: '\u001b[32m',
}
}
};
};
Я в основном хочу разделить все зависимости для КАЖДЫЙ модуль (т. Е. Моя папка-компонент выше называется name
).Как бы я это сделал?(Или ... какие у меня варианты?)
Процесс обработки данных и данных:
1. User opens website. Default dependencies are loaded.
2. User navigates to /dashboard
3. Resources (node_modules & other dependencies) for /dashboard is loaded
Этот GIF взят из Эта статья реакции иллюстрируетэто хорошо (Загрузка зависимостей чанка для этого модуля).