The introduction
For general projects, especially mobile terminal projects,we are familiar with webpack+ Vue, Webpack + React and other packages into a single page application. A lot of what I’ve found on Github is packaging all of our modules into one big JS package (even CSS) and importing it in HTML.
As is known to all, a single page application dependent module will have a lot of great performance issues, when our web application more and more big, we could not put all the functions on the same page, then usually do is according to the classification module of function, the application into multiple single page, doing so will help later function in the extension.
To build multi-page applications, we should consider the following questions:
- Single-page applications should have common sections of code, and we want to keep these common sections out to avoid double reference loading.
- As the business grows, new single-page applications may be added, but the build-related code will not be changed when new applications are added.
Let’s look at the configuration of a typical one-page application:
const path = require('path');
const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const { WebPlugin } = require('web-webpack-plugin');
module.exports = {
entry: {
app: './main.js'// Chunk app JS execution entry file}, output: {filename:'[name]_[chunkhash:8].js'// Add to the output file namehashValue path: the path. The resolve (__dirname,'./dist'),
},
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader'// exclude: path.resolve(__dirname, exclude: path.resolve(__dirname, exclude: path.resolve(__dirname, exclude: path.'node_modules'),}, {test: / \. CSS /, / / to increase support for CSS file / / extracted the Chunk of CSS code into separate files use: ExtractTextPlugin. Extract ({use:'css-loader? minimize'}),},]}, plugins: [// use WebPlugin, each WebPlugin is corresponding to an HTML file new WebPlugin({template:'./template.html'// HTML template file path filename:'index.html'// output HTML filename}), new ExtractTextPlugin({filename: '[name]_[contenthash:8].css',// add to output CSS filenamehashValue}), new DefinePlugin({// define the NODE_ENV environment variable as production to remove parts of the React code that are needed for development'process.env': {
NODE_ENV: JSON.stringify('production'}}), // compress the output of JS code new UglifyJsPlugin({// the most compact output beautify:false// Delete all comments comments:false// Ignore the unimportant... })]};Copy the code
The most important thing here is the WebPlugin, which enables us to automatically output HTML files and introduce packaged modules. Although this has provided great convenience for us to package applications, it is still a troublesome problem for the management of multiple pages. If we want to add a page we need to create a new webPlugin instance and add configuration items in the entry entry.
The solution
Here we use AutoWebPlugin to build our multi-page application. The directory structure of the project source code is as follows:
The following requirements can be seen from the directory structure:
- All single-page application code needs to be placed in a directory, such as the Pages directory;
- A single page application corresponds to a separate folder, for example, the last generated index.html related code is in the index directory, the same as login. HTML:
- Each single page application has an index.js file in its directory as the entry execution file. AutoWebP Lugin has a mandatory directory structure for project sections. From experience, this is an elegant directory specification that splits the code properly and allows newcomers to quickly understand the structure of the project for future maintenance.
The webpack configuration file is as follows:
const path = require('path');
const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const { AutoWebPlugin } = require('web-webpack-plugin'); Const AutoWebPlugin = new AutoWebPlugin() const AutoWebPlugin = new AutoWebPlugin('pages', {
template: './template.html'// postEntrys: ['./common.css'],// All pages rely on this common CSS style file // Extract common code for all pages: {name:'common',// Extract the name of the common code Chunk},}); Module.exports = {// AutoWebPlugin generates an entry configuration for all single-page applications it finds. // Autowebplugin. entry gets an entry configuration entry: Autowebplugin.entry ({// here you can add the extra Chunk entry you need}), output: {filename:'[name]_[chunkhash:8].js'// Add to the output file namehashValue path: the path. The resolve (__dirname,'./dist'),
},
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader'// exclude: path.resolve(__dirname, exclude: path.resolve(__dirname, exclude: path.resolve(__dirname, exclude: path.'node_modules'),}, {test: / \. CSS /, / / to increase support for CSS file / / extracted the Chunk of CSS code into separate files use: ExtractTextPlugin. Extract ({use:'css-loader? minimize'},},}, plugins: [autoWebPlugin, new ExtractTextPlugin({filename: '[name]_[contenthash:8].css',// add to the output CSS file namehashValue}), new DefinePlugin({// define the NODE_ENV environment variable as production to remove parts of the React code that are needed for development'process.env': {
NODE_ENV: JSON.stringify('production'}}), // compress the output of JS code new UglifyJsPlugin({// the most compact output beautify:false// Delete all comments comments:false// Ignore the unimportant... })]};Copy the code
AutoWebPlugin finds the index and login folders in the Pages directory, treats them as two single-page applications, and generates a Chunk configuration and a WebPlugin configuration for each single-page application, respectively. The Chunk name of each one-page application is the same as the folder name, which means that the autowebplugin.entry () method returns:
{ "index:["./pages/index/index.js","./common.css"]."login": ["./pages/login/index.js","./common.css"]}Copy the code
<html>
<head>
<meta charset="UTF-8"> <! Where the rest of the CSS is injected that the page depends on --> <! --STYLE--> <! -- Ignore irrelevant code --> </head> <body> <div id="app"></div> <! The rest of the JavaScript injection that the page depends on --> <! --SCRIPT--> <! -- Ignore irrelevant code --> </body> </ HTML >Copy the code
Notice two important new keywords in the template file
and
,
What do they mean?
Since this template file is used as a template for all single-page applications in the project, each single-page application will have its own name because the Chunk names that need to be injected into the current page are not fixed.
and
ensures that all the resources the page depends on are injected into the generated HTML template.
The web-webpack-plugin can figure out which resources each page depends on, for example, for login.html,
- The common CSS code on which all pages rely is common.css;
- Common JavaScript code that all pages rely on common.js;
- Only the CSS code that this page relies on login.css;
- Only the JavaScript code login.css that this page relies on.
<! --STYLE-->
<! --SCRIPT-->
- Inject csS-type files into <! –STYLE–> < span STYLE = “box-sizing: border-box! Important; –STYLE–> Insert the end of the HTML HEAD tag if it does not exist.
- Inject JavaScript type files into <! –SCRIPT–> position, if < <! –SCRIPT–> If not present, inject the end of the HTML BODY tag.
The code packaged after the NPM run build is as follows:
login.html:
<html>
<head>
<meta charset="UTF-8"> <! -- The page depends on the rest of the CSS injection place --> <link rel="stylesheet" href="common_7cc98ad0.css">
<link rel="stylesheet" href="login_e31e214b.css"> <! -- Ignore irrelevant code --> </head> <body> <div id="app"></div> <! The rest of the JavaScript injection that the page depends on --> <script SRC ="common_bdac69cb.js"></script>
<script src="login_0a3feca9.js"></script> <! -- Ignore irrelevant code --> </body> </ HTML >Copy the code
Reference reading:
- https://www.npmjs.com/package/web-webpack-plugin
- Easy to understand Webpack