webpack搭建React环境与各配置详解

1 基础配置与详解

1.1 初始化项目

mkdir ReacDemo
cd  ReacDemo
mkdir src
mkdir dist
npm init -y

1.2 安装webpack

安装webpack 和webpack服务

cnpm i webpack webpack-cli webpack-dev-server -D

在项目跟目录下新建webpack配置文件webpack.config.js,配置文件的初始化内容为

module.exports = {
    mode: "development",//表识开发环境
    entry: ["./src/index.js"], // 入口文件
    output: { // 打包后输出目录
        // 输出目录
        path: path.join(__dirname, "dist"),
        // 文件名称
        filename: "bundle.js"
    },
    module:{}, // loader配置
    plugins:[],// 插件配置
    devServer:{}//开发服务
}

1.3 babel编译ES6,JSX等

安装babel依赖包

cnpm i babel-loader @babel/core @babel/preset-env  @babel/plugin-transform-runtime   @babel/preset-react -D

  • babel-loader webpack使用babel解析用到的loader,打包转换成es5语法
  • @babel/core babel核心包,使用babel解析的合并包
  • @babel/preset-env babel官方预设的一些转换babel需要用到的babel依赖
  • @babel/preset-react 解析react的jsx语法预设的一些依赖
    关于babel的详细介绍具体可到babel官网了解

在项目跟目录下(和src同级)新建.babelrc文件,文件的内容为

{
  "presets": ["@babel/preset-env","@babel/preset-react"],
  "plugins": ["@babel/plugin-transform-runtime"]
}

在webpack.config.js文件中配置babel,打包转换es6及以上语法

module: {
        rules:[
            {
                test: /\.js?$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: "babel-loader"
                    }
                ]
            }
        ]
    }

1.4 插件 CleanWebpackPlugin

其实 clean-webpack-plugin 很容易知道它的作用,就是来清除文件的,就是说在为生产环境编译文件的时候,先把 build或dist (就是放生产环境用的文件) 目录里的文件先清除干净,再生成新的.

cnpm install  clean-webpack-plugin -D
// 注意这个引入的坑,最新版的需要这样引入,而不是直接const CleanWebpackPlugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
 
// 在webpack.config.js的plugins下配置
plugins: [
    new CleanWebpackPlugin() 
]

1.5 使用插件 HtmlWebpackPlugin

  • 为html文件中引入的外部资源如script、link动态添加每次compile后的hash,防止引用缓存的外部文件问题
  • 可以生成创建html入口文件,比如单页面可以生成一个html文件入口,配置N个html-webpack-plugin可以生成N个页面入口

插件参数详解

  • title 生成html文件的标题
  • filename 输出的html的文件名称
  • template html模板所在的文件路径,根据自己的指定的模板文件来生成特定的 html 文件
  • inject 注入选项。有四个选项值 true, body, head, false.
  1. true:默认值,script标签位于html文件的 body 底部
  2. body:script标签位于html文件的 body 底部(同 true)
  3. head:script 标签位于 head 标签内
  4. false:不插入生成的 js 文件,只是单纯的生成一个 html 文件
  • favicon 给生成的 html 文件生成一个 favicon。属性值为 favicon 文件所在的路径名
  • minify minify 的作用是对 html 文件进行压缩,minify 的属性值是一个压缩选项或者 false 。默认值为false, 不对生成的 html 文件进行压缩。
plugins:[
        new HtmlWebpackPlugin({
    //部分省略,具体看minify的配置
    minify: {
     //是否对大小写敏感,默认false
    caseSensitive: true,
    
    //是否简写boolean格式的属性如:disabled="disabled" 简写为disabled  默认false
    collapseBooleanAttributes: true,
    
    //是否去除空格,默认false
    collapseWhitespace: true,
    
    //是否压缩html里的css(使用clean-css进行的压缩) 默认值false;
    minifyCSS: true,
    
    //是否压缩html里的js(使用uglify-js进行的压缩)
    minifyJS: true,
    
    //Prevents the escaping of the values of attributes
    preventAttributesEscaping: true,
    
    //是否移除属性的引号 默认false
    removeAttributeQuotes: true,
    
    //是否移除注释 默认false
    removeComments: true,
    
    //从脚本和样式删除的注释 默认false
    removeCommentsFromCDATA: true,
    
    //是否删除空属性,默认false
    removeEmptyAttributes: true,
    
    //  若开启此项,生成的html中没有 body 和 head,html也未闭合
    removeOptionalTags: false, 
    
    //删除多余的属性
    removeRedundantAttributes: true, 
    
    //删除script的类型属性,在h5下面script的type默认值:text/javascript 默认值false
    removeScriptTypeAttributes: true,
    
    //删除style的类型属性, type="text/css" 同上
    removeStyleLinkTypeAttributes: true,
    
    //使用短的文档类型,默认false
    useShortDoctype: true,
    }
    }),
]
  • hash hash选项的作用是 给生成的 js 文件一个独特的 hash 值,该 hash 值是该次 webpack 编译的 hash 值。默认值为 false

配置webpack.config.js

// 引入
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      title: 'Hello World app',
      minify: { // 压缩HTML文件
        removeComments: true, // 移除HTML中的注释
        collapseWhitespace: true, // 删除空白符与换行符
        minifyCSS: true// 压缩内联css
      },
      filename: 'index.html', // 最终创建的文件名
      template: path.join(__dirname, 'src/template.html') // 指定模板路径
    })
  ]

1.6 使用 source-map

source map就是帮助我们定位到错误信息位置的文件。正确的配置source map,能够提高开发效率,更快的定位到错误位置。详细了解请点击
在webpack.config.js中选项加上如下这句话

devtool:"cheap-module-eval-source-map",// 开发环境配置
devtool:"cheap-module-source-map",   // 线上生成配置

1.7 使用 WebpackDevServer

webpack-dev-server就是在本地为搭建了一个小型的静态文件服务器,有实时重加载的功能,为将打包生成的资源提供了web服务
开发环境中我们可以启动一个devServer静态文件服务器,预览我们的项目,配置如下

  • contentBase: 静态文件地址
  • port: 端口号
  • host: 主机
  • overlay: 如果出错,则在浏览器中显示出错误
  • compress: 服务器返回浏览器的时候是否启动gzip压缩
  • open: 打包完成自动打开浏览器
  • hot: 模块热替换 需要webpack.HotModuleReplacementPlugin插件
  • inline: 实时构建
  • progress: 显示打包进度
  • devtool: 生成代码映射,查看编译前代码,利于找bug
  • webpack.NamedModulesPlugin: 显示模块的相对路径。
devServer: {
    hot: true,
    contentBase: path.join(__dirname, "./dist"),
    host: "0.0.0.0", // 可以使用手机访问
    port: 8080,
    historyApiFallback: true, // 该选项的作用所有的404都连接到index.html
    proxy: {
      // 代理到后端的服务地址,会拦截所有以api开头的请求地址
      "/api": "http://localhost:3000"
    }
  }

1.8 编译css和scss

cnpm install css-loader style-loader sass-loader node-sass -D
 
{
  test: /\.scss$/,
    use: [
      "style-loader", // 创建style标签,并将css添加进去
      "css-loader", // 编译css
      "sass-loader" // 编译scss
    ]
}

1.9 集成postcss

最关心的还是这有啥用啊?自动增加前缀, postcss-cssnext允许你使用未来的css特性,并做一些兼容处理

  1. 修改webpack配置文件下的module
cnpm install  postcss-loader postcss-cssnext -D
 
{
    test: /\.scss$/,
        use: [
            "style-loader", // 创建style标签,并将css添加进去
            "css-loader", // 编译css
            "postcss-loader",
            "sass-loader" // 编译scss
        ]
}

  1. 在跟目录下新建一个postcss.config.js文件,文件内容为:
module.exports = {
    plugins: {
        'postcss-cssnext': {}
    }
};

1.10 处理图片

  • file-loader file-loader 可以指定要复制和放置资源文件的位置,以及如何使用版本哈希命名以获得更好的缓存。此外,这意味着 你可以就近管理图片文件,可以使用相对路径而不用担心部署时 URL 的问题。使用正确的配置,webpack 将会在打包输出中自动重写文件路径为正确的 URL
  • url-loader 允许你有条件地将文件转换为内联的 base-64 URL (当文件小于给定的阈值),这会减少小文件的 HTTP 请求数。如果文件大于该阈值,会自动的交给 file-loader 处理
cnpm i file-loader url-loader -D
 
file-loader 解决css等文件中引入图片路径的问题
url-loader 当图片较小的时候会把图片BASE64编码,大于limit参数的时候还是使用file-loader 进行拷贝
{
    test: /\.(png|jpg|jpeg|gif|svg)/,
    use: {
      loader: 'url-loader',
      options: {
        outputPath: 'images/', // 图片输出的路径
        limit: 10 * 1024
      }
    }
}

2 webpack 优化

2.1 alias对文件路径优化

  • extension: 指定extension之后可以不用在require或是import的时候加文件扩展名,会依次尝试添加扩展名进行匹配
  • alias: 配置别名可以加快webpack查找模块的速度
    修改webpack.config.js 其中resolve和配置中的entry同级
resolve: {
    extension: [".js", ".jsx"],
    alias: {
      "@": path.join(__dirname, "src"),
      pages: path.join(__dirname, "src/pages"),
      router: path.join(__dirname, "src/router")
    }
  }

2.2 MiniCssExtractPlugin ,抽取 css 文件

如果不做配置,我们的css是直接打包进js里面的,我们希望能单独生成css文件。 因为单独生成css,css可以和js并行下载,提高页面加载效率

cnpm install mini-css-extract-plugin -D
 
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
 
 {
        test: /\.scss$/,
        use: [
          // "style-loader", // b不再需要style-loader要已经分离处理
          MiniCssExtractPlugin.loader,
          "css-loader", // 编译css
          "postcss-loader",
          "sass-loader" // 编译scss
        ]
      },
 
 plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css"
    })
  ]

2.3 代码分割按需加载、提取公共代码

我们现在看到,打包完后,所有页面只生成了一个bundle.js,当我们首屏加载的时候,就会很慢。因为他也下载了别的页面的js了,也就是说,执行完毕之前,页面是 完!全!空!白!的!。 如果每个页面单独打包自己的js,就可以在进入页面时候再加载自己 的js,首屏加载就可以快很多

// optimization 和配置中的entry同级
// 代码分割按需加载、提取公共代码
    optimization: {
        usedExports: true,
        splitChunks: {
            chunks: "all", // 所有的 chunks 代码公共的部分分离出来成为一个单独的文件
            cacheGroups: {
                // 公共代码打包分组配置
                jquery: {
                    name: 'jquery',
                    test: /[\\/]node_modules[\\/]jquery[\\/]/
                },
                vendors: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendors'
                }
            }
        },
    },

2.4 文件压缩

webpack4只要在生产模式下, 代码就会自动压缩

mode:productioin

2.5 暴露全局变量

new webpack.ProvidePlugin({
      $: 'jquery', // npm
    })

2.6 DllPlugin插件打包第三方类库

项目中引入了很多第三方库,这些库在很长的一段时间内,基本不会更新,打包的时候分开打包来提升打包速度,而DllPlugin动态链接库插件,其原理就是把网页依赖的基础模块抽离出来打包到dll文件中,当需要导入的模块存在于某个dll中时,这个模块不再被打包,而是去dll中获取

未完待续。。。

你可能感兴趣的:(webpack搭建React环境与各配置详解)