胡家华 преди 5 години
родител
ревизия
d2ec14da1e
променени са 8 файла, в които са добавени 134 реда и са изтрити 13 реда
  1. 55 3
      README.md
  2. 3 0
      common/index.js
  3. 1 1
      package.json
  4. 1 0
      src/index/index.js
  5. 3 0
      src/search/index.js
  6. 6 0
      src/search/tree-shaking.js
  7. 39 7
      webpack.dev.js
  8. 26 2
      webpack.prod.js

+ 55 - 3
README.md

@@ -1,3 +1,4 @@
1
+
1 2
 #### 插件记录 
2 3
 ##### 多页面应用 匹配入口文件
3 4
 - 使用`glob`插件,`glob.sync(path.join(__dirname ,"./src/*/index.js"))`方法会匹配`src`目录下  
@@ -25,6 +26,7 @@ new HtmlWebpackPlugin({
25 26
 `{ "presets": [ "@babel/preset-env", "@babel/preset-react" ] }`
26 27
 ##### js优化
27 28
 > webpack 4 版本自带了`UglifyJsPlugin`插件,会对js进行压缩
29
+
28 30
 ##### css优化
29 31
 - 压缩css`OptimizeCSSAssetsPlugin`,需要用到`cssnano`库
30 32
 ```
@@ -81,8 +83,7 @@ new OptimizeCSSAssetsPlugin({ // 压缩css
81 83
 
82 84
 - chunkhash
83 85
 > 根据不同的入口文件(Entry)进行依赖文件解析、构建对应的chunk,生成对应的哈希值,在生产环境里把一些公共库和程序入口文件区分开,单独打包构建,接着我们采用chunkhash的方式生成哈希值,那么只要我们不改动公共库的代码,就可以保证其哈希值不会受影响。
84
-> 
85
-**但是这样又有一个问题,因为我们是将样式作为模块import到JavaScript文件中的,所以它们的chunkhash是一致的**
86
+> **但是这样又有一个问题,因为我们是将样式作为模块import到JavaScript文件中的,所以它们的chunkhash是一致的**
86 87
 
87 88
 - contenthash
88 89
 > contenthash是针对文件内容级别的,只有你自己模块的内容变了,那么hash值才改变
@@ -132,11 +133,62 @@ rules: [
132 133
     }],
133 134
   },
134 135
 ]
136
+
135 137
 ```
138
+##### source-map 开发环境开启,线上关闭
139
+配置详见:[webpack devtool](https://www.webpackjs.com/configuration/devtool/)
140
+
136 141
 ##### 辅助工具
137 142
 - `CleanWebpackPlugin` 构建完成之前删除dist目录
138 143
 ```
139 144
 plugins:[
140 145
   new CleanWebpackPlugin()
141 146
 ]
142
-```
147
+```
148
+##### 基础库分离
149
+- 使用`SplitChunksPlugin`插件将`React React-dom`通过CDN引入
150
+- `chunks` 参数说明
151
+  - async 只分离异步引入的库
152
+  - initial 只分离同步引入的库
153
+  - all 分离引入的库
154
+配置详见: [split-chunks-plugin/](https://www.webpackjs.com/plugins/split-chunks-plugin/#optimization-splitchunks)
155
+
156
+```
157
+plugins:[
158
+  optimization : {
159
+    splitChunks: {
160
+      cacheGroups: {
161
+        commons: {
162
+          test: /(react|react-dom)/,
163
+          name: "vendors",
164
+          chunks: 'all'
165
+        }
166
+      }
167
+    }
168
+  }
169
+或者
170
+optimization : {
171
+    splitChunks: {
172
+      minSize: 0, // 引用的模块大小,
173
+      cacheGroups: {
174
+        commons: {
175
+          // test: /(react|react-dom)/,
176
+          name: "commons",
177
+          chunks: 'all',
178
+          minChunks: 3, // 最少引用了两次
179
+        }
180
+      }
181
+    }
182
+  }
183
+```
184
+
185
+##### 摇树优化
186
+
187
+一个模块有多个方法,只要引用了一个方法,这个文件都会被打包到bundle中,`tree shaking`就是只把引用了到方法打入bundle中,没用到的方法会在`uglify`阶段去除掉
188
+
189
+- 使用:
190
+`webpack`默认支持,在`mode:production`的情况下默认开启,在`.babelrc`文件中设置`modules:false`即可
191
+
192
+- 要求
193
+必须是`es6`的语法
194
+

+ 3 - 0
common/index.js

@@ -0,0 +1,3 @@
1
+export function common () {
2
+    return 'common'
3
+}

+ 1 - 1
package.json

@@ -35,7 +35,7 @@
35 35
   "scripts": {
36 36
     "build": "webpack --config webpack.prod.js",
37 37
     "watch": "webpack --watch",
38
-    "dev": "webpack-dev-server --config webpack-dev.js --open"
38
+    "dev": "webpack-dev-server --config webpack.dev.js --open"
39 39
   },
40 40
   "dependencies": {
41 41
     "lib-flexible": "^0.3.2"

+ 1 - 0
src/index/index.js

@@ -1,6 +1,7 @@
1 1
 
2 2
 import React from 'react'
3 3
 import ReactDom from 'react-dom'
4
+import { common } from '../../common' // 提取公共代码测试,使用了两次
4 5
 class Home extends React.Component {
5 6
     render(){
6 7
         return (

+ 3 - 0
src/search/index.js

@@ -3,6 +3,9 @@ import React from 'react'
3 3
 import ReactDom from 'react-dom'
4 4
 import './less/search.less'
5 5
 import img from './images/screenshot.gif'
6
+import { common } from '../../common' // 提取公共代码测试,使用了两次
7
+import { a } from './tree-shaking' // 摇树优化,只打包引用的函数
8
+
6 9
 class Search extends React.Component {
7 10
     render(){
8 11
         return (

+ 6 - 0
src/search/tree-shaking.js

@@ -0,0 +1,6 @@
1
+export function a () {
2
+    console.log('a')
3
+}
4
+export function b () {
5
+    console.log('b')
6
+}

+ 39 - 7
webpack.dev.js

@@ -2,12 +2,43 @@ const path = require('path')
2 2
 const webpack = require('webpack')
3 3
 // const CleanWebpackPlugin = require("clean-webpack-plugin")
4 4
 const { CleanWebpackPlugin } = require('clean-webpack-plugin');
5
-
5
+const HtmlWebpackPlugin = require("html-webpack-plugin")
6
+const glob = require('glob')
7
+const setMPA = () => {
8
+    const entry = {}
9
+    const htmklWebpackPlugins = [];
10
+    const entryFiles = glob.sync(path.join(__dirname ,"./src/*/index.js")) // 匹配入口文件
11
+    console.log('entryFiles',entryFiles)
12
+    Object.keys(entryFiles).map((index) => {
13
+      const entryFile = entryFiles[index]
14
+      const match = entryFile.match(/src\/(.*)\/index\.js/)
15
+      const pageName = match && match[1]
16
+      entry[pageName] = entryFile; // 设置entry
17
+      htmklWebpackPlugins.push( // 设置html模版
18
+        new HtmlWebpackPlugin({
19
+          template: path.join(__dirname, `src/${pageName}/index.html`),
20
+          filename: `${pageName}.html`,
21
+          chunks: [pageName],
22
+          inject: true, // 注入css/js
23
+          minify: { // 模板格式设置
24
+            html5:true,
25
+            collapseWhitespace: true ,
26
+            preserveLicenseComments: false ,
27
+            minifyJS: true ,
28
+            minifyCSS: true,
29
+            removeComments: true,
30
+          }
31
+        }),
32
+      )
33
+    })
34
+    return {
35
+      entry,
36
+      htmklWebpackPlugins ,
37
+    }
38
+  }
39
+  const {entry,htmklWebpackPlugins} = setMPA()
6 40
 module.exports = {
7
-    entry: {
8
-        app: './src/index.js',
9
-        search: './src/search.js'
10
-    },
41
+    entry,
11 42
     output: {
12 43
         path: path.join(__dirname, 'dist'),
13 44
         filename: '[name].js'
@@ -51,9 +82,10 @@ module.exports = {
51 82
     plugins:[
52 83
         new webpack.HotModuleReplacementPlugin(),
53 84
         new CleanWebpackPlugin(),
54
-    ],
85
+    ].concat(htmklWebpackPlugins),
55 86
     devServer: {
56 87
         contentBase: path.join(__dirname ,"dist"),
57 88
         hot: true ,
58
-    }
89
+    },
90
+    devtool: 'cheap-source-map'
59 91
 }

+ 26 - 2
webpack.prod.js

@@ -19,7 +19,7 @@ const setMPA = () => {
19 19
       new HtmlWebpackPlugin({
20 20
         template: path.join(__dirname, `src/${pageName}/index.html`),
21 21
         filename: `${pageName}.html`,
22
-        chunks: [pageName],
22
+        chunks: ['vendors', pageName],
23 23
         inject: true, // 注入css/js
24 24
         minify: { // 模板格式设置
25 25
           html5:true,
@@ -121,5 +121,29 @@ module.exports = {
121 121
       cssProcessor: require('cssnano')
122 122
     }),
123 123
     new CleanWebpackPlugin(), // 构建完成之前删除原来到构建目录
124
-  ].concat(htmklWebpackPlugins)
124
+  ].concat(htmklWebpackPlugins),
125
+  // optimization : {
126
+  //   splitChunks: {
127
+  //     cacheGroups: {
128
+  //       commons: {
129
+  //         test: /(react|react-dom)/,
130
+  //         name: "vendors",
131
+  //         chunks: 'all'
132
+  //       }
133
+  //     }
134
+  //   }
135
+  // }
136
+  optimization : {
137
+    splitChunks: {
138
+      minSize: 0, // 引用的模块大小,
139
+      cacheGroups: {
140
+        commons: {
141
+          // test: /(react|react-dom)/,
142
+          name: "commons",
143
+          chunks: 'all',
144
+          minChunks: 3, // 最少引用了两次
145
+        }
146
+      }
147
+    }
148
+  }
125 149
 }