webpack 4.x总结梳理

274 阅读7分钟

webpack

上一篇:项目部署CentOS 7.2

介绍

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

  • 理解依赖关系图

任何时候,一个文件依赖于另一个文件,webpack 就把此视为文件之间有 依赖关系 。这使得 webpack 可以接收非代码资源(non-code asset)(例如图像或 web 字体),并且可以把它们作为 依赖 提供给你的应用程序

理解四个核心概念:

  • 入口(entry):指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始【每个依赖项随即被处理,最后输出到称之为 bundles 的文件中】

    指定一个入口起点(或多个入口起点)。默认值为 ./src

  • 输出(output):告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist

    整个应用程序结构,都会被编译到你指定的输出路径的文件夹中

  • loader(解析器):loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块

    webpack 自身只理解 JavaScript

    • loader 有两个目标
      • test 属性:用于标识出应该被对应的 loader 进行转换的某个或某些文件
      • use 属性:表示进行转换时,应该使用哪个 loader
  • 插件(plugins):插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量

最后还有一个模式--》通过选择 development 或 production 之中的一个

         module.exports = {
              mode: 'production'
           };

总结详解

前言:

    module.exports = {
      //入口文件的配置项
      entry: {},
      //出口文件的配置项
      output: {},
      //模块:例如解读CSS,图片如何转换,压缩
      module: {},
      //插件,用于生产模版和各项功能
      plugins: [],
      //配置webpack开发服务功能
      devServer: {}
    }

入口entry(单入口与多入口)

  • 写法

    • 单入口

        const config = {
        //字符串----------------(是下面对象的简写)
          entry:'./path/to/my/entry/file.js'
          
        //对象  
        entry:  {
            'main':'./path/to/my/entry/file.js'
          }
        
        //数组
        /*
        *    在你想要多个依赖文件一起注入,并且将它们的依赖导向(graph)到一个“chunk”时,传入数组的方式就很有用
        *   简单说-》 把几个文件合并到一起的时候,给entry中传入数组就行了
        */
          entry: ['name.js',  './path/to/my/entry/file.js'],
         };
        module.exports = config;
      
    • 多入口:entry: {[entryChunkName: string]: string|Array<string}

        const config = {
       
        //对象  
        entry:  {
            pageOne: './src/pageOne/index.js',
            pageTwo: './src/pageTwo/index.js',
            pageThree: './src/pageThree/index.js'
          }
        };
      
        module.exports = config;
      

分离 应用程序(app) 和 第三方库(vendor) 入口 文档

动态入口 文档

输出(output)

  • 写法

    • __dirname:node模块,表示当前目录

          // 定义webpack如何输出的选项
          output: {
             // path.resolve用来拼接文件多级目录
            // __dirname 为当前文件所在全路径地址
            path: path.resolve(__dirname, "dist"), // string
           // 「入口(entry chunk)」文件命名模版
           // 多入口设置唯一,单入口可以是死的名
            filename: "[chunkhash].js", // string
          // 按需加载(on-demand-load)或加载外部资源(external resources)(如图片、文件等
            publicPath: "/assets/", // string
            /* 其它高级配置 */
          }
      
    • filename: "[chunkhash].js"

    Snipaste_2019-08-21_15-01-36.png

    • publicPath: "/assets/" 文档

      webpack-dev-server 也会默认从 publicPath 为基准,使用它来决定在哪个目录下启用服务,来访问 webpack 输出的文件。

      Snipaste_2019-08-21_15-07-59.png

loader(解析器)

  • Vue需要什么解析器呢?【VueLoaderPlugin插件必须引入文档

    • vue-loader(重要点):处理 .vue 文件--》【单独一个 vue-loader 并不能解决问题:vue-template-compiler(vue-template-compiler是vue-loader必须的依赖)】

      • 安装

                   npm install -D vue-loader vue-template-compiler
        
      • 代码

              // webpack.config.js
              const VueLoaderPlugin = require('vue-loader/lib/plugin')
              module.exports = {
                  module: {
                  rules: [
                    // ... 其它规则
                    {
                      test: /\.vue$/,
                      loader: 'vue-loader'
                    }
                  ]
                },
                plugins: [
                  // 请确保引入这个插件!
                  new VueLoaderPlugin()
                ]
              }
        
    • vue-template-compiler:用于把 Vue 的模板文件(应该指.vue)预编译为渲染函数,避免运行时再编译带来的性能开销

    • 为了能够编写预处理css--->node-sass以及sass-loader 【node-sass 把 sass编译成css,sass-loader把webpack的loader】

      ss

      • 安装

            npm install -D sass-loader node-sass
        
      • 代码

        module.exports = {
              module: {
                rules: [
                  // ... 忽略其它规则
        
                  // 普通的 `.scss` 文件和 `*.vue` 文件中的
                  // `<style lang="scss">` 块都应用它
                  //在 vue 中,我们更推荐使用 vue-style-loader
                  {
                    test: /\.scss$/,
                    use: [
                      'vue-style-loader',
                      'css-loader',
                      'sass-loader'
                    ]
                  },
                    //sass-loader 会默认处理不基于缩进的 scss 语法。为了使用基于缩进的 sass 语法,
                    //使用indentedSyntax为true
                  {
                    test: /\.sass$/,
                    use: [
                      'vue-style-loader',
                      'css-loader',
                      'sass-loader?indentedSyntax'
                    ],
                  },
                ]
              },
              // 插件忽略
            }
        
      • 遇到无法加载的情况(vue-loader变成如下)

                     {
                    test: /\.vue$/,
                    loader: 'vue-loader',
                    options: {
                      loaders: {
                        // 由于sass-loader(奇怪)将SCSS作为其默认的解析模式,我们映射
                        // lang的“scss”和“sass”值属于右边的配置。
                        // 其他预处理器应该开箱即用,没有像这样的加载器配置。
                        'scss': [ //从左到右解析
                          'vue-style-loader',
                          'css-loader',
                          'sass-loader'
                        ],
                        'sass': [ //从左到右解析
                          'vue-style-loader',
                          'css-loader',
                          'sass-loader?indentedSyntax'  //排除 node_modules
                        ]
                      }
                    }
                  }
        
      • 处理css

        • 安装

            npm i css-loader -D 
          
        • 代码

                  {
                    test: /\.css$/,
                    use: [
                      'vue-style-loader',
                      'css-loader'
                    ],
                  }
          
      • 需要能够解析es6更高级的语法:babel-loader ,@babel/core,@babel/preset-env

        • 安装

                      npm i @babel/core babel-loader @babel/preset-env --save-dev
          
      • 代码

                         //.babelrc
                        {
                          "presets": [
                            ["@babel/preset-env", {
                              "targets": {
                                "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
                              }
                            }]
                          ]
                        }
        
                -------------------------------------------------------------
                    {
                        test: /\.js$/,
                        loader: 'babel-loader',
                        exclude: file => (
                                /node_modules/.test(file) &&
                                !/\.vue\.js/.test(file)
                              )
                      }
        
      • TypeScript

        • 安装

              npm install -D typescript ts-loader
          
        • 代码

                   // webpack.config.js
                       module.exports = {
                         resolve: {
                           // 将 `.ts` 添加为一个可解析的扩展名。
                           extensions: ['.ts', '.js']
                         },
                         module: {
                           rules: [
                             // ... 忽略其它规则
                             {
                               test: /\.ts$/,
                               loader: 'ts-loader',
                               options: { appendTsSuffixTo: [/\.vue$/] }
                             }
                           ]
                         },
                         // ...plugin omitted
                       }
          
      • 处理图片资源 :file-loader【url-loader,他可以将html以及css中的图片打包成base64,性能优化减少https(适合小图,因此加上limit限制)】

              npm i url-loader file-loader -D
        
        • url-loader依赖file-loader,当图片超过限制时,等同于file-loader

              {
                      test: /\.(png|jpg|gif|svg)$/,
                      loader: 'url-loader',
                      options: {
                        limit: 10000, // 根据需求自行填写
                        name: '[name].[ext]?[hash]'
                      }
                    }
          
  • 引入字体图标【npm i url-loader file-loader -D】

                      {
                        test: /\.(woff|woff2|eot|ttf|otf|svg)$/,
                        use: [
                          {
                            loader: 'url-loader',
                            options: {
                              limit: 8192
                            }
                          }
                        ]
                      }
    
    • loader部分基本配置就出来了【css=css-loader/sass=node-sass与sass-loader/vue=vue-loader/js=bable-loader/file=file-loader】

            module.exports = {
              module: {
                rules: [
                  {
                    test: /\.css$/,
                    use: [
                      'vue-style-loader',
                      'css-loader'
                    ],
                  },
                  {
                    test: /\.scss$/,
                    use: [
                      'vue-style-loader',
                      'css-loader',
                      'sass-loader'
                    ],
                  },
                  {
                    test: /\.sass$/,
                    use: [
                      'vue-style-loader',
                      'css-loader',
                      'sass-loader?indentedSyntax'
                    ],
                  },
                  {
                    test: /\.vue$/,
                    loader: 'vue-loader',
                    options: {
                      loaders: {
                        'scss': [
                          'vue-style-loader',
                          'css-loader',
                          'sass-loader'
                        ],
                        'sass': [
                          'vue-style-loader',
                          'css-loader',
                          'sass-loader?indentedSyntax'
                        ]
                      }
                      // other vue-loader options go here
                    }
                  },
                  {
                    test: /\.js$/,
                    loader: 'babel-loader',
                    exclude: /node_modules/
                  },
                  {
                        test: /\.(png|jpg|gif|svg)$/,
                        loader: 'url-loader',
                        options: {
                          limit: 10000, // 根据需求自行填写
                          name: '[name].[ext]?[hash]'
                        }
                      }
                ]
              }
              //其他配置省略
            }
      
  • React 需要啥呢?

    • js兼容==》

      • babel-loader:使用 Babel 转换 JavaScript依赖关系的 Webpack 加载器

      • @babel/core:即 babel-core,将 ES6 代码转换为 ES5

      • @babel/preset-env:即 babel-preset-env,根据您要支持的浏览器,决定使用哪些 transformations / plugins 和 polyfills,例如为旧浏览器提供现代浏览器的新特性

        yarn add babel-loader @babel/core @babel/preset-env

    • 安装react转换 babel-preset-react【**注:babel 7 使用了 @babel 命名空间来区分官方包,因此以前的官方包 babel-xxx 改成了 @babel/xxx】

      • @babel/preset-react:即 babel-preset-react,针对所有 React 插件的 Babel 预设,例如将 JSX 转换为函数

           yarn add babel-preset-react --dev
        
    • 代码(支持jsx后缀)

                    module.exports = {
                      module: {
                        rules: [
                          {
                            test: /\.(js|jsx)$/,
                            exclude: /node_modules/,
                            use: {
                              loader: 'babel-loader'
                            }
                          }
                        ]
                      }
                    };
      
                   ------------------------------------------------------
                           // .babelrc
                      {
                      "presets": ["@babel/preset-env", "@babel/preset-react"]
                    }
      
      • 配置css==>安装 css-loader 和 style-loader 作为 dev 依赖项

          npm i css-loader style-loader -D
        
        • 代码

                 {
                    test: /\.css$/,
                    use: ['style-loader', 'css-loader']
                  }
          
        • css模块化

                {
                        test: /\.css$/,
                        use: [
                          {
                            loader: 'style-loader'
                          },
                          {
                            loader: 'css-loader',
                            options: {
                              modules: true,
                              importLoaders: 1,
                              localIdentName: '[name]_[local]_[hash:base64]',
                              sourceMap: true,
                              minimize: true
                            }
                          }
                        ]
                      }
          
        • 编写预编译css

          • 安装

                npm install css-loader sass-loader style-loader  -D
            
          • 代码

            module.exports = {
                  module: {
                    rules: [
                      // ... 忽略其它规则
            
                      // 普通的 `.scss` 文件和 `*.vue` 文件中的
                      // `<style lang="scss">` 块都应用它
                      //在 vue 中,我们更推荐使用 vue-style-loader
                      {
                        test: /\.scss$/,
                        use: [
                          'style-loader', 
                          'css-loader', 
                          'sass-loader'
                        ]
                      },
                        //sass-loader 会默认处理不基于缩进的 scss 语法。为了使用基于缩进的 sass 语法,
                        //使用indentedSyntax为true
                      {
                        test: /\.sass$/,
                        use: [
                          'style-loader',
                          'css-loader',
                          'sass-loader?indentedSyntax'
                        ],
                      },
                    ]
                  },
                  // 插件忽略
                }
            
          • 处理图片资源 :file-loader【url-loader,他可以将html以及css中的图片打包成base64,性能优化减少https(适合小图,因此加上limit限制)】

                         npm i url-loader file-loader -D
            
            • url-loader依赖file-loader,当图片超过限制时,等同于file-loader

                        {
                                test: /\.(png|jpg|gif|svg)$/,
                                loader: 'url-loader',
                                options: {
                                  limit: 10000, // 根据需求自行填写
                                  name: '[name].[ext]?[hash]'
                                }
                              }
              
            • 引入字体图标【npm i url-loader file-loader -D】

                            {
                              test: /\.(woff|woff2|eot|ttf|otf|svg)$/,
                              use: [
                                {
                                  loader: 'url-loader',
                                  options: {
                                    limit: 8192
                                  }
                                }
                              ]
                            }
              

插件(plugins)

  • HtmlWebpackPlugin来将我们output的js和html结合起来

    • 安装

        npm install html-webpack-plugin --save
      
    • 代码

      • filename:可以设置html输出的路径和文件名

      • template:可以设置已哪个html文件为模版(更多的参数)

        const HtmlWebpackPlugin = require('html-webpack-plugin');
        ...
        plugins: [
            new HtmlWebpackPlugin({
                filename: './dist/index.html',
                template: './index.html',
            })
        ]
        
  • mini-css-extract-plugin可提取css文件到单独的文件, 最好只在生产环境下使用,以便于热重载

    • 安装

             npm install -D mini-css-extract-plugin
      
    • 代码

            const MiniCssExtractPlugin = require('mini-css-extract-plugin')
            ...
            new MiniCssExtractPlugin({
              filename: '[name].[hash].css',
              chunkFilename: '[id].[hash].css'
            })
      
  • autoprefixer可以自动帮你添加浏览器前缀

    • 安装

         npm i autoprefixer postcss-loader -D
      
    • 代码

           module:{
                rules:[
                    {
                        test:/\.scss$/,
                        use:[‘style-loader‘,‘css-loader‘,‘sass-loader‘,‘postcss-loader‘]
                    },
                    {
                        test: /\.css$/,
                        use: ["style-loader", "css-loader", "postcss-loader"]
                    }
                ]
            }
      
    • 在webpack.config.js文件同级目录中,新建postcss.config.js文件,并且添加如下代码

        module.exports = {
            plugins:[
                require(‘autoprefixer‘)
            ]
        }
      
  • vue骨架屏 饿了吗设计推出

  • clean-webpack-plugin:webpack 会生成文件,然后将这些文件放置在 dist文件夹中,但是 webpack 无法追踪到哪些文件是实际在项目中用到的。通常,在每次构建前清理 dist

    • 安装

        npm i -D clean-webpack-plugin
      
    • 代码

           const CleanWebpackPlugin = require('clean-webpack-plugin')
      
           plugins: [
             new CleanWebpackPlugin(["dist"])
           ]
      
  • HotModuleReplacementPlugin热更新(不是局部的)【依赖于webpack-dev-server--》查看下面配置webpack-dev-server】

              plugins: [
                      new webpack.HotModuleReplacementPlugin()
                  ]
    
    • (React实现局部)可以使用react-hot-loader

      • 安装包

          npm install --save-dev react-hot-loader
        
      • 修改.babelrc配置文件(加上)

          {
                  plugins: ["react-hot-loader/babel"]
              }
        

了解现代框架带的局部更新

devServer

  • 开服务( webpack-dev-server 的选项。)更多的配置

              devServer: {
                  contentBase: path.join(__dirname, "dist"),//对外提供的访问内容的路径
                  compress: true,//是否启用gzip压缩
                  port: 9000//提供访问的端口
              }
    
    • 配置webpack-dev-server(搭配HotModuleReplacementPlugin热更新(局部)具体看这个

      • webpack.config.js【mode与hot选择webpack里设置还是package里设置】

                const webpack = require('webpack');
        
                     module.exports = {
                     + mode: 'development',
                       devServer: {
                     +  hot: true //这个也可以在script里设置
                       },
                     + plugins: [
                     +   new webpack.HotModuleReplacementPlugin()
                     + ]
                     };
        
      • package.json

              "start": "webpack-dev-server --hot --mode development --open",
        

devtool(介绍】)

//介绍

  • 在开发环境中我们可以使用

          module.exports = {
            devtool: 'cheap-module-eval-source-map'
          }
    
  • 在正式环境中我们可以使用

          module.exports = { 
            devtool: 'cheap-module-source-map';
          }
    

reslove(官方文档

  • 基本设置(目的:提高打包速度)

    • modules:告诉 webpack 解析模块时应该搜索的目录【添加一个目录到模块搜索目录,此目录优先于 node_modules-》文档

    • alias:使用别名

    • extensions:项目引入文件的时候 ,数组里有的后缀,引入路径的文件后缀不需要带了【频率高的文件尽量写在前面】

          resolve: { //  解析模块
              modules: ['node_modules']
              extensions: [".js", ".json", ".jsx", ".css"], // 用到的文件的扩展
              alias: { // 模块别名列表
                "module": "new-module"
          	  },
            }
      

代理跨域(详细文档

        devServer: {
            proxy: {
              '/api': 'http://localhost:3000'
            }
          }
        }

环境选择

  • 生产环境

              if (process.env.NODE_ENV === 'production') {
                module.exports.devtool = '#source-map'
                //。。。。。。
              }
    

package.json

  • hot也可以在devServer里设置

      "scripts": {
        "start": "webpack-dev-server --hot --mode development --open",
        "build": "webpack --mode production"
      }
    

现代化框架所需要的基础包依赖

  • Vue

      npm i vue vue-router vuex -S
    
  • React

    • react-router: 实现了路由的核心功能

    • react-router-dom: 基于react-router,加入了在浏览器运行环境下的一些功能,例如:Link组件,会渲染一个a标签,Link组件源码a标签行; BrowserRouter和HashRouter组件,前者使用pushState和popState事件构建路由,后者使用window.location.hash和hashchange事件构建路由

        npm i react react-dom redux react-redux react-router react-router-dom -S