Sfoglia il codice sorgente

通用多文件打包

胡家华 5 anni fa
commit
b24607b133

+ 6 - 0
.babelrc

@@ -0,0 +1,6 @@
1
+{
2
+    "presets": [
3
+        "@babel/preset-env",
4
+        "@babel/preset-react"
5
+    ]
6
+}

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
1
+node_modules
2
+dist
3
+yarn-error.log

+ 142 - 0
README.md

@@ -0,0 +1,142 @@
1
+#### 插件记录 
2
+##### 多页面应用 匹配入口文件
3
+- 使用`glob`插件,`glob.sync(path.join(__dirname ,"./src/*/index.js"))`方法会匹配`src`目录下  
4
+所有等文件夹中等index.js入口文件(开发按照约定,入口文件为`index.js`)
5
+##### 设置打包后到模板页以及注入js,css等 `HtmlWebpackPlugin`
6
+```
7
+new HtmlWebpackPlugin({
8
+  template: path.join(__dirname, `src/${pageName}/index.html`),
9
+  filename: `${pageName}.html`,
10
+  chunks: [pageName],
11
+  inject: true, // 注入css/js
12
+  minify: { // 模板格式设置
13
+    html5:true,
14
+    collapseWhitespace: true ,
15
+    preserveLicenseComments: false ,
16
+    minifyJS: true ,
17
+    minifyCSS: true,
18
+    removeComments: true,
19
+  }
20
+})
21
+```
22
+##### 支持react,jsx,es6/7新特性
23
+- 需要使用 `@babel/core @babel/preset-react @babel/preset-env babel-loader`  
24
+- 需要新建`.babelrc`文件且加入
25
+`{ "presets": [ "@babel/preset-env", "@babel/preset-react" ] }`
26
+##### js优化
27
+> webpack 4 版本自带了`UglifyJsPlugin`插件,会对js进行压缩
28
+##### css优化
29
+- 压缩css`OptimizeCSSAssetsPlugin`,需要用到`cssnano`库
30
+```
31
+new OptimizeCSSAssetsPlugin({ // 压缩css
32
+  assetNameRegExp: /\.css$/g,
33
+  cssProcessor: require('cssnano')
34
+}),
35
+```
36
+> 如果`module.rules`中使用了`style-loader css-loader less-loader`此时会将css压缩至css中  
37
+可通过`MiniCssExtractPlugin`生成单独css文件
38
+
39
+- css自动补全前缀`postcss-loader`和`autoprefixer`
40
+```
41
+{
42
+  loader: 'postcss-loader',
43
+  options: {
44
+    plugins: () => [
45
+      require('autoprefixer')({ // 自动补全
46
+        overrideBrowserslist:["last 2 version", ">1%", 'ios 7'],
47
+      })
48
+    ]
49
+  }
50
+}
51
+```
52
+- 移动端rem单位转换`px2rem-loader`,同时通过`raw-loader`包内联静态资源文件引入`node_modules/lib-flexible/flexible.js`(需下载`lib-flexible`库,且需要安装到正式环境到依赖`yarn add lib-flexible -S`)
53
+```
54
+{
55
+  loader: "px2rem-loader",
56
+  options: {
57
+    remUnit: 75, // 1rem = 75px
58
+    remPrecesion: 8, // px转换rem到小数位
59
+  }
60
+}
61
+```
62
+- 在`index.html`模板页引入内联资源
63
+```
64
+// 静态资源导入
65
+<script type="text/javascript">
66
+  // 静态资源导入
67
+  ${require('raw-loader!babel-loader!../../node_modules/lib-flexible/flexible.js')}
68
+</script>
69
+```
70
+
71
+```
72
+<head>
73
+  <!-- 静态资源导入 -->
74
+  ${require('raw-loader!./meta.html')}
75
+</head>
76
+```
77
+
78
+##### 文件指纹 hash,chunkhash,contenthash
79
+- hash
80
+> 一旦文件改变,重新打包将会导致整个项目hash改变,整个项目的缓存将失效
81
+
82
+- chunkhash
83
+> 根据不同的入口文件(Entry)进行依赖文件解析、构建对应的chunk,生成对应的哈希值,在生产环境里把一些公共库和程序入口文件区分开,单独打包构建,接着我们采用chunkhash的方式生成哈希值,那么只要我们不改动公共库的代码,就可以保证其哈希值不会受影响。
84
+> 
85
+**但是这样又有一个问题,因为我们是将样式作为模块import到JavaScript文件中的,所以它们的chunkhash是一致的**
86
+
87
+- contenthash
88
+> contenthash是针对文件内容级别的,只有你自己模块的内容变了,那么hash值才改变
89
+
90
+解决办法: 对入口文件使用`chunkhash`,对css文件使用`contenthash`,**如果对css使用文件指纹,需要取消使用`style-loader`,因为前者是生成hash css文件,后者是将css打入html中**
91
+
92
+```
93
+output: {
94
+  path: path.join(__dirname, 'dist'),
95
+  filename: '[name]_[chunkhash:8].js' // chunkhash
96
+},
97
+```
98
+```
99
+plugins:[
100
+  new MiniCssExtractPlugin({
101
+    filename: '[name]_[contenthash:8].css' // contenthash
102
+  })
103
+]
104
+```
105
+
106
+```
107
+module: {
108
+  rules:[
109
+    {
110
+    test: /.less$/,
111
+    use:[
112
+      // 'style-loader',// 将css插入到html style标签,如果要使用contenthash生成css文件,需要注释
113
+      MiniCssExtractPlugin.loader ,
114
+      'css-loader',
115
+      'less-loader'
116
+    ]
117
+    }
118
+  ]
119
+}
120
+```
121
+##### 文件压缩
122
+- `url-loader`
123
+```
124
+rules: [
125
+  {
126
+    test: /\.(png|jpg|gif)$/i,
127
+    use: [{
128
+      loader: 'url-loader',
129
+      options: {
130
+        limit: 8192, // 限制大小
131
+      },
132
+    }],
133
+  },
134
+]
135
+```
136
+##### 辅助工具
137
+- `CleanWebpackPlugin` 构建完成之前删除dist目录
138
+```
139
+plugins:[
140
+  new CleanWebpackPlugin()
141
+]
142
+```

+ 43 - 0
package.json

@@ -0,0 +1,43 @@
1
+{
2
+  "name": "webpack-learing",
3
+  "version": "1.0.0",
4
+  "main": "index.js",
5
+  "repository": "http://47.106.15.140:8001/hujiahua/webpack-learing.git",
6
+  "author": "胡家华 <hjhgzem@163.com>",
7
+  "license": "MIT",
8
+  "devDependencies": {
9
+    "@babel/core": "^7.5.5",
10
+    "@babel/preset-env": "^7.5.5",
11
+    "@babel/preset-react": "^7.0.0",
12
+    "autoprefixer": "^9.6.1",
13
+    "babel-loader": "^8.0.6",
14
+    "clean-webpack-plugin": "^3.0.0",
15
+    "css-loader": "^3.2.0",
16
+    "cssnano": "^4.1.10",
17
+    "file-loader": "^4.2.0",
18
+    "glob": "^7.1.4",
19
+    "html-webpack-plugin": "^3.2.0",
20
+    "less": "^3.10.3",
21
+    "less-loader": "^5.0.0",
22
+    "mini-css-extract-plugin": "^0.8.0",
23
+    "optimize-css-assets-webpack-plugin": "^5.0.3",
24
+    "postcss-loader": "^3.0.0",
25
+    "px2rem-loader": "^0.1.9",
26
+    "raw-loader": "0.5.1",
27
+    "react": "^16.9.0",
28
+    "react-dom": "^16.9.0",
29
+    "style-loader": "^1.0.0",
30
+    "url-loader": "^2.1.0",
31
+    "webpack": "^4.39.3",
32
+    "webpack-cli": "^3.3.7",
33
+    "webpack-dev-server": "^3.8.0"
34
+  },
35
+  "scripts": {
36
+    "build": "webpack --config webpack.prod.js",
37
+    "watch": "webpack --watch",
38
+    "dev": "webpack-dev-server --config webpack-dev.js --open"
39
+  },
40
+  "dependencies": {
41
+    "lib-flexible": "^0.3.2"
42
+  }
43
+}

+ 20 - 0
src/index/index.html

@@ -0,0 +1,20 @@
1
+<!DOCTYPE html>
2
+<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
3
+<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
4
+<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
5
+<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
6
+    <head>
7
+        <meta charset="utf-8">
8
+        <meta http-equiv="X-UA-Compatible" content="IE=edge">
9
+        <title>index</title>
10
+        <meta name="description" content="">
11
+        <meta name="viewport" content="width=device-width, initial-scale=1">
12
+        <link rel="stylesheet" href="">
13
+    </head>
14
+    <body>
15
+        <!--[if lt IE 7]>
16
+            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
17
+        <![endif]-->
18
+        <div id='root'></div>
19
+    </body>
20
+</html>

+ 17 - 0
src/index/index.js

@@ -0,0 +1,17 @@
1
+
2
+import React from 'react'
3
+import ReactDom from 'react-dom'
4
+class Home extends React.Component {
5
+    render(){
6
+        return (
7
+            <div className='search-text'>
8
+                index 
9
+            </div>
10
+        )
11
+    }
12
+}
13
+
14
+ReactDom.render(
15
+    <Home/>,
16
+    document.getElementById("root")
17
+)

BIN
src/search/font/SourceHanSerifSC-Heavy.otf


BIN
src/search/images/screenshot.gif


+ 26 - 0
src/search/index.html

@@ -0,0 +1,26 @@
1
+<!DOCTYPE html>
2
+<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
3
+<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
4
+<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
5
+<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
6
+    <head>
7
+        <meta charset="utf-8">
8
+        <meta http-equiv="X-UA-Compatible" content="IE=edge">
9
+        <title>search</title>
10
+        <meta name="description" content="">
11
+        <meta name="viewport" content="width=device-width, initial-scale=1">
12
+        <link rel="stylesheet" href="">
13
+        <!-- 静态资源导入 -->
14
+        ${require('raw-loader!./meta.html')}
15
+        <script type="text/javascript">
16
+            // 静态资源导入
17
+            ${require('raw-loader!babel-loader!../../node_modules/lib-flexible/flexible.js')}
18
+        </script>
19
+    </head>
20
+    <body>
21
+        <!--[if lt IE 7]>
22
+            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
23
+        <![endif]-->
24
+        <div id='root'></div>
25
+    </body>
26
+</html>

+ 21 - 0
src/search/index.js

@@ -0,0 +1,21 @@
1
+
2
+import React from 'react'
3
+import ReactDom from 'react-dom'
4
+import './less/search.less'
5
+import img from './images/screenshot.gif'
6
+class Search extends React.Component {
7
+    render(){
8
+        return (
9
+            <div className='search-text'>
10
+                search
11
+                测试watch text webpack-dev-server
12
+                <img src={ img } width={100}/>
13
+            </div>
14
+        )
15
+    }
16
+}
17
+
18
+ReactDom.render(
19
+    <Search/>,
20
+    document.getElementById("root")
21
+)

+ 12 - 0
src/search/less/search.less

@@ -0,0 +1,12 @@
1
+
2
+@font-face{
3
+    font-family: 'SourceHanSerifSC-Heavy';
4
+    src: url('../font/SourceHanSerifSC-Heavy.otf') format('truetype');
5
+}
6
+
7
+.search-text{
8
+    font-size: 20px;
9
+    color: red;
10
+    background-color: #ccc;
11
+    display: flex;
12
+}

File diff suppressed because it is too large
+ 10 - 0
src/search/meta.html


+ 59 - 0
webpack.dev.js

@@ -0,0 +1,59 @@
1
+const path = require('path')
2
+const webpack = require('webpack')
3
+// const CleanWebpackPlugin = require("clean-webpack-plugin")
4
+const { CleanWebpackPlugin } = require('clean-webpack-plugin');
5
+
6
+module.exports = {
7
+    entry: {
8
+        app: './src/index.js',
9
+        search: './src/search.js'
10
+    },
11
+    output: {
12
+        path: path.join(__dirname, 'dist'),
13
+        filename: '[name].js'
14
+    },
15
+    mode: 'development',
16
+    // mode: 'production',
17
+    watch: true ,
18
+    module: {
19
+        rules:[
20
+            {
21
+                test: /.js$/,
22
+                use:'babel-loader'
23
+            },
24
+            {
25
+                test: /.less$/,
26
+                use:[
27
+                    'style-loader',
28
+                    'css-loader',
29
+                    'less-loader'
30
+                ]
31
+            },
32
+            {
33
+                test: /.(png|jpg|gif|jpeg)$/,
34
+                use:[
35
+                    {
36
+                        loader: 'url-loader',
37
+                        options: {
38
+                            limit: 10240
39
+                        }
40
+                    }
41
+                ]
42
+            },
43
+            {
44
+                test: /.(otf|ttf|woff|woff2|eot)$/,
45
+                use:[
46
+                    'file-loader',
47
+                ]
48
+            }
49
+        ]
50
+    },
51
+    plugins:[
52
+        new webpack.HotModuleReplacementPlugin(),
53
+        new CleanWebpackPlugin(),
54
+    ],
55
+    devServer: {
56
+        contentBase: path.join(__dirname ,"dist"),
57
+        hot: true ,
58
+    }
59
+}

+ 125 - 0
webpack.prod.js

@@ -0,0 +1,125 @@
1
+const path = require('path')
2
+const webpack = require('webpack')
3
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
4
+const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
5
+const HtmlWebpackPlugin = require("html-webpack-plugin")
6
+const { CleanWebpackPlugin } = require('clean-webpack-plugin');
7
+const glob = require('glob')
8
+const setMPA = () => {
9
+  const entry = {}
10
+  const htmklWebpackPlugins = [];
11
+  const entryFiles = glob.sync(path.join(__dirname ,"./src/*/index.js")) // 匹配入口文件
12
+  console.log('entryFiles',entryFiles)
13
+  Object.keys(entryFiles).map((index) => {
14
+    const entryFile = entryFiles[index]
15
+    const match = entryFile.match(/src\/(.*)\/index\.js/)
16
+    const pageName = match && match[1]
17
+    entry[pageName] = entryFile; // 设置entry
18
+    htmklWebpackPlugins.push( // 设置html模版
19
+      new HtmlWebpackPlugin({
20
+        template: path.join(__dirname, `src/${pageName}/index.html`),
21
+        filename: `${pageName}.html`,
22
+        chunks: [pageName],
23
+        inject: true, // 注入css/js
24
+        minify: { // 模板格式设置
25
+          html5:true,
26
+          collapseWhitespace: true ,
27
+          preserveLicenseComments: false ,
28
+          minifyJS: true ,
29
+          minifyCSS: true,
30
+          removeComments: true,
31
+        }
32
+      }),
33
+    )
34
+  })
35
+  return {
36
+    entry,
37
+    htmklWebpackPlugins ,
38
+  }
39
+}
40
+const {entry,htmklWebpackPlugins} = setMPA()
41
+module.exports = {
42
+  entry,
43
+  output: {
44
+    path: path.join(__dirname, 'dist'),
45
+    filename: '[name]_[chunkhash:8].js' // hash, chunkhash, cententhash 哈希
46
+  },
47
+  // mode: 'development',
48
+  mode: 'production',
49
+  watch: true ,
50
+  module: {
51
+    rules:[
52
+      {
53
+        test: /.js$/,
54
+        use:'babel-loader'
55
+      },
56
+      {
57
+        test: /.css$/,
58
+        use:[
59
+          // 'style-loader',// 将css插入到html style标签,如果要使用contenthash生成css文件,需要注释
60
+          MiniCssExtractPlugin.loader ,
61
+          'css-loader'
62
+        ]
63
+      },
64
+      {
65
+        test: /.less$/,
66
+        use:[
67
+          // 'style-loader',// 将css插入到html style标签,如果要使用contenthash生成css文件,需要注释
68
+          MiniCssExtractPlugin.loader ,
69
+          'css-loader',
70
+          'less-loader',
71
+          {
72
+            loader: 'postcss-loader',
73
+            options: {
74
+              plugins: () => [
75
+                require('autoprefixer')({ // 自动补全
76
+                  overrideBrowserslist:["last 2 version", ">1%", 'ios 7']
77
+                })
78
+              ]
79
+            }
80
+          }, {
81
+            loader: "px2rem-loader",
82
+            options: {
83
+              remUnit: 75, // 1rem = 75px
84
+              remPrecesion: 8, // px转换rem到小数位
85
+            }
86
+          }
87
+        ]
88
+      },
89
+      {
90
+        test: /.(png|jpg|gif|jpeg)$/,
91
+        use:[
92
+          {
93
+            loader: 'file-loader',
94
+            options: {
95
+              // limit: 10240
96
+              name: '[name]_[hash:8].[ext]'
97
+            }
98
+          }
99
+        ]
100
+      },
101
+      {
102
+        test: /.(otf|ttf|woff|woff2|eot)$/,
103
+        use:[
104
+          {
105
+            loader: 'file-loader',
106
+            options: {
107
+              // limit: 10240
108
+              name: '[name]_[hash:8][ext]'
109
+            }
110
+          }
111
+        ]
112
+      }
113
+    ]
114
+  },
115
+  plugins:[
116
+    new MiniCssExtractPlugin({
117
+      filename: '[name]_[contenthash:8].css'
118
+    }),
119
+    new OptimizeCSSAssetsPlugin({ // 压缩css
120
+      assetNameRegExp: /\.css$/g,
121
+      cssProcessor: require('cssnano')
122
+    }),
123
+    new CleanWebpackPlugin(), // 构建完成之前删除原来到构建目录
124
+  ].concat(htmklWebpackPlugins)
125
+}

File diff suppressed because it is too large
+ 6680 - 0
yarn.lock