Webpack-基础知识

2020/7/18 Webpack
// 什么是webpack
1. webpack是一个模块打包工具
2. npm init 文件名 // 在文件中生成package.json文件
3. npm webpack index.js // 使用全局的webpack对index.js进行打包
4. npx webpack index.js // 使用当前项目的webpack对index.js进行打包
5. npm webpack --config 文件名 // 以这个文件为配置文件进行打包
6. webpack.config.js是webpack的配置文件
7. 基础的配置参数
    module.export = {
      mode: 'production'(压缩代码)/'development'(不压缩代码)
      entry: './src/index.js', // 需要打包的文件
      output: {
        filename: '打包后的文件名',
        path: '打包后的文件存放路径'
      },
      module: {
        rules: [{
          test: /\.jpg$/,
          use: {
            loader: 'url-loader', // 只处理 css 中引入的图片,html 中引入的图片需要使用 html-loader
            options: {
              // 小于5kb的图片用base64格式产出
              // 否则依然使用file-loader的形式,产出url格式
              // 执行规则是从下往上执行,在正式环境下时下面会再配置 file-loader
              limit: 5 * 1024,
              // 打包到img目录下
              outputPath: '/img/,
              // 设置图片的cdn地址,也可以同一在外面的output中设置
              // 修改静态文件的引入路径
              publicPath: 'http://cdn.abc.com'
            }
          }
        }]
      }
    }
----------------------------------------------------------------------------------------------
// 什么是loader
1. loader是打包方案,打包非js结尾后缀的文件,针对不同文件类型进行打包
2. loader的执行规则是从右往左,从下往上,使用多个loader时配置use要用数组而不是对象
3. file-loader // 可处理图片、txt、icon文件
4. style-loader + css-loader // 把样式挂载到html + 合并css
5. sass-loader // 可处理sass文件
6. postcss-loader + autoprefixer // 添加厂商前缀
7. css-loader 可以配置 options,React 中的模块化 css 就是通过这个实现的
  use: ['style-loader', {
    loader: 'css-loader',
    options: {
      modules: true // 还可以配置对象,可以配置里面具体如何生成 css 名称
    }
  }]
----------------------------------------------------------------------------------------------
// 什么是plugins
1. plugins相当于插件,是在运行到某个时刻执行某些事情
2. HtmlWebpackPlugin在打包结束后自动生成一个html文件,并把打包后的js自动引入到这个html中
   const htmlwebpackplugin = require('html-webpack-plugin')
   module.export = {
    plugins: [
      new HtmlWebpackPlugin({
        template: 'src/index.html', // 模板,使得新生成的html文件跟模板文件内容一样
        filename: 'index.html',
        chunks: ['index', 'vendor', 'common'] // 在生成index.html后会把code splitting代码分割后所对应的name文件引入
      })
    ]
   }
3. Clean自动清空某个文件夹下的东西
   const CleanWebpackPlugin = require('clean-webpack-plugin')
   module.export = {
    plugins: [
      new CleanWebpackPlugin(['dist'])
    ]
   }
----------------------------------------------------------------------------------------------
// module、chunk、bundle的区别
1. module: 相当于是各个还没有进行打包的源码文件,在webpack中一切都是模块
2. chunk: 在打包时可能只有一个模块的文件也可能是多模块合并成的文件
3. bundle: chunk最终的输出文件,可能一个也可能多个
----------------------------------------------------------------------------------------------
// entry需要打包的文件,打包2次,一个main,一个sub,output也要改
1. module.export = {
    entry: {
      main: './src/index.js',
      sub: './src/sub.js'
    }
  }
----------------------------------------------------------------------------------------------
// 打包后的输出
1. module.export = {
    output: {
      publicpath: 'webchenjie.cn', // 在新生成的html文件引入的js文件路径前面加上webchenjie.cn
      filename: '[name].[contentHash:8].js', // 打包后的文件名字,[name]是占位符
      path: path.resolve(__dirname, 'dist')
    }
  }
----------------------------------------------------------------------------------------------
// dev和pro区分打包
1. 两个配置环境不同,则需要两个配置文件,对于相同的配置可以提取到一个公用的配置文件中,最后通过webpack-merge合并导出
2. npm install webpack-merge -D
    const merge = require('webpack-merge')
    const devConfig/proConfig = { '配置内容' }
    module.export = merge(commonConfig, devConfig/proConfig)package.json的scripts中配置:
    "dev": "webpack-dev-server --config ./build/webpack.dev.js"
3. 环境变量
   module.export env => {
      if (env && env.production) {
        return merge(commonConfig, proConfig)
      } else {
        return merge(commonConfig, devConfig)
      }
   }package.json文件的script中
    "build": "webpack --env.production --config ./webpack.common.js"
    通过命令传入参数判断使用哪个环境进行打包
4. 使用production时:
    会自动开启代码压缩
    vue、react等会自动删掉调试代码 // 如开发环境的warning
    启用Tree-Shaking
----------------------------------------------------------------------------------------------
// devtool,映射(sourceMap),当代码写错时,在控制台查看源代码或打包后的代码提示第几行错误
1. 在生产环境中:
    module.export = {
      mode: 'production',
      devtool: 'cheap-module-source-map'
    }
2. 在开发环境中:
    module.export = {
      mode: 'development',
      devtool: 'cheap-module-eval-source-map'
    }
3. devtool的值:
    inline // 不生成map文件,没在dist目录,以base64格式存储
    cheap // 精确到行,不到列,只管打包的业务代码
    module // 精确到行,不到列,包括loader或第三方模块
    eval // 最快,打包关联性多的文件,不推荐,也不会生成map文件
----------------------------------------------------------------------------------------------
// 监听文件变化自动打包
1. webpackDevServer不会生成dist目录而放在内存
    在package.json中的script添加命令
    "dev": "webpack-dev-server" // npm run dev,可自动打包,起了个服务器,自动刷新页面
    module.export = {
      devServer: {
        contentBase: './dist', // 在这个路径下起服务器
        open: true, // 打包完自动开打页面
        port: 8080, // 端口号
        proxy: {} // 代理
      }
    }
2.package.json中的script添加命令
    "watch": "webpack --watch" // npm run watch,可自动打包,当文件发生变化时
3. 通过express和webpack-dev-middleware自己写服务器
----------------------------------------------------------------------------------------------
// caching浏览器缓存
1. 当文件内容变了,哈希值就会变,就会去加载否则不会重新加载
2. module.export = {
      output: {
        filename: '[name].[contenthash].js',
        chunkFileName: '[name].[contenthash].js'
      }
   }
----------------------------------------------------------------------------------------------
// shimming垫片,自动载入库
1. module.export = {
      plugins: [
        // webpack.providePlugin 会先从当前路径开始查找,再查找 node_modules
        new webpack.providePlugin({
          $: 'jQuery' // 用了$就会自动引入jQuery
        })
      ]
   }
----------------------------------------------------------------------------------------------
// library封装库发布到npm上的配置
1. module.export = {
      output: {
        librayTarget: 'umd/this/window/...', // 别人使用时可以用import/require等方式引入
        library: 'root', // 把方法挂载到root上去
        externals: ['lodash'] // 忽略lodash打包
      }
   }
----------------------------------------------------------------------------------------------
// PWA
1. 利用缓存即使服务器挂了也能展示出页面
2. const workboxWebpackPlugin = require('workbox-webpack-plugin')
   module.export = {
     plugins: [
       new workboxWebpackPlugin.Generatesw({
         clientsClaim: true,
         skipwaiting: true
       })
     ]
   }
----------------------------------------------------------------------------------------------
// typescript
1. npm install ts-loader
   module.export = {
     module: {
       rules: [
         {
           test: /\.tsx?$/,
           use: 'ts-loader',
           exclude: /node_modules/
         }
       ]
     }
   }
----------------------------------------------------------------------------------------------
// proxy代理转发
1. module.export = {
      devServer: {
        proxy: {
          '/vue/api': {
            target: 'https://webchenjie.cn', // 转发到哪个地址
            secure: false, // 对https生效
            changeOrigin: true, // 针对爬虫,对origin支持
            headers: { // 请求头
              host: '192.168.100.20'
            },
            pathRewrite: { // 路径重写,针对开发环境,上线需要后端配合跳转
              a.json: b.json
            }
          }
        },
        historyApiFallback: true // 解决单页应用路由问题
      }
   }
----------------------------------------------------------------------------------------------
// ESlint,代码检测,会生成.eslintrc文件,会降低打包速度,也可使用eslintcr文件的配置进行检测
1. npm install eslint -D
   npm install selint-loader -D
   module.export = {
     devServer: {
       overlay: true // 当发现代码检测不通过时会在浏览器里弹框提示
     },
     moudle: {
       rules: [
         {
           test: /\.js$/,
           exclude: /node_modules/,
           use: ['babel-loader', 'eslint-loader']
         }
       ]
     }
   }
----------------------------------------------------------------------------------------------
// 多页面打包配置
1. 在配置文件中写多个HtmlWebpackPlugin和增加多个entry入口
----------------------------------------------------------------------------------------------
// 其他
1. loader自己编写是一个函数,单独一个文件
2. plugin自己编写是一个类,单独一个文件,所以使用时需要引入并且new
3. 开发环境可以不合并、分析、压缩、拆分,会提高构建速度
4. compiler 钩子是构建之前的处理,compilation 钩子是构建时的处理
5. 在 webpack 打包的时候,可以在 js 文件中混用 require 和 export,但是不能混用 import 以及 module.exports
  因为 webpack2 中不允许混用 import 和 module.exports, 解决办法就是统一改成 ES6 的方式编写即可
6. target 配置默认是 'web',如果是 Node 项目可以改成 'node'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
Last Updated: 2024/6/11 14:20:38
    飘向北方
    那吾克热-NW,尤长靖