美文网首页
webpack4+ 基础配置及使用

webpack4+ 基础配置及使用

作者: leleo | 来源:发表于2019-11-25 11:16 被阅读0次

    现在webpack4出来了,需要重新记录一下webpack4的基本配置,为了以后节省新项目配置时间,很多东西一下子记不起来的时候,可以翻看下自己做的笔记,仅此而已。

    如果你看到了这篇文章,说明你对webpack有兴趣,想了解webpack。如果一点都不懂,可以先看下API文档
    https://www.webpackjs.com/concepts/

    其实最好最全的文档就是官方提供的API文档,但是有很多地方,我们不知道怎么用,说话很官方。对于新手来说很难去理解。下面我把我理解的一些用法写出来,仅供大家参考:

    要用webpack,首先需要下载,现在webpack4+以上版本下载webpack需要和webapck-cli一起下载使用,可以达到基础的零配置使用webpack

    我们知道webpack运行环境是基于node的,所以使用webpack需要先安装nodejs。

    安装

    下载nodejs

    下载nodejs直接去官网下载就行,官网链接:https://nodejs.org/en/

    初始化项目

    接下在我们就打开一个空的目录,随便你在哪里打开都可以。再用cmd工具进入到这个目录下,如果不知道cmd的基本用法可以百度或google一波基本操作。

    webpack init
    
    安装webpack

    如果你使用 webpack 4+ 版本,你还需要安装 webapck-cli。现在下载安装webapck和webapck-cli,最好是下载到本地,可以避免多项目冲突问题。可以控制版本问题。更容易分别升级项目,不会影响其他项目
    注意:如果下载不了,可以用淘宝的镜像下载,速度快,可以直接百度淘宝镜像设置,这里不解释了。

    npm install webpack webpack-cli --save-dev
    

    下载完可以看到node_modules文件夹和package-lock.json文件,说明下载成功

    起步(基本演示代码)

    简单demo

    下面我们开始写一个简单demo,创建src目录,在src目录里面创建index.js

    src(文件夹)
      |-- idnex.js(文件)
    

    index.js文件内容如下:

    function context() {
      const element = document.createElement('div');
      element.innerHTML = 'Hello webpack';
      return element;
    }
    document.body.appendChild(context());
    

    webpack是零配置,所以现在就可以开始打包我们的index.js文件了,在cmd上运行代码:

    npx webpack
    

    这时候我们可以看到我们的文件里多出了dist文件夹,dist文件夹里有一个main.js文件。这个文件就是我们打包后的文件。 如果我们的js文件有依赖,我们下面代码用import引入一个js文件:

    src(文件夹)
      | -- index.js(文件)
      | -- modu.js (文件)
    

    修改index.js文件和添加modu.js文件:
    index.js文件内容如下:

     import modu from './module';
    document.body.appendChild(modu());
    

    添加modu.js文件内容如下:

    function context() {
      const element = document.createElement('div');
      element.innerHTML = 'Hello webpack';
      return element;
    }
    module.exports = context;
    

    在cmd上运行代码:

    npx webpack
    

    这样也是可以打包成功的。

    webpack零配置打包就已经好了,但是我们的项目不可能那么简单。

    上面代码是很基础的代码。一般我们在项目中基本不会碰到那么简单的打包。没有用webpack真正的强大功能

    js打包配置

    问题来了,下面我们需要解决那些js打包问题

    • 配置入口 ---- 单入口和多入口如何配置
    • 配置出口 ---- 插件代码,公共代码,私有代码如何分离打包
    • 代码缓存 ---- 如何添加哈希值
    • 环境配置 ---- 配置测试环境和生成环境
    • 编译代码 ---- 把浏览器不兼容的代码,比如typeSacript或者es6+代码编译成es5,做到浏览器能兼容
    • 合并代码 ---- webpack默认代码合并
    • 压缩混淆代码 ---- 配置生产模式,自动压缩文件,开发模式没有压缩

    需要了解这些,我们就要手动创建一个webpack.config.js 配置文件

    添加webpack.config.js 配置文件

    在项目根目录手动创建一个webpack.config.js文件,添加如下代码:

      const path = require('path');
    
      module.exports = {
        entry: {
          app: './src/index.js',
        },
        output: {
          filename: 'main.js',
          path: path.resolve(__dirname, 'dist')
        }
      };
    

    所谓的webpack零配置,其实就是webapck默认配置就是上面的代码,你可以不配置

    下面开始执行我们不用npx webpack来执行文件了,直接用npm来运行我们的配置,我们重新配置下package.json文件,在package.json文件配置我们的webpack打包命令,在package.json文件里,找到scripts,在里面添加命令如下:

    "scripts": {
        "start": "webpack --config webpack.config.js"
    }
    
    配置入口文件
    1. 配置单入口文件
      module.exports = {
        ···
        entry: {
          app: './src/index.js',   // 单入口文件,路径跟名字是可以自己随意修改
        },
        output: {
          filename: 'main.js',   // filename 是填写自己的文件名,也可以直接用[name].js
          path: path.resolve(__dirname, 'dist')  // path:需要填写路径。path.resolve()是nodejs的代码合并。__dirname是当前目录路径。'dist' 是根目录下的dist文件名。
        }
        ···
      };
    
    1. 配置多入口文件
      const path = require('path');
      module.exports = {
        entry: { // 多入口文件需要以数组的形式传入
          'index': ['./src/index.js'], 
          'modu': ['./src/modu.js'],
        },
        output: {
          filename: '[name].js',  // 如果是多入口文件,名字必须是[name].js
          path: path.resolve(__dirname, 'dist')
        }
      };
        ···
      };
    
    配置出口文件
    1. 配置单出入口文件
      module.exports = {
        ···
        entry: {
          app: './src/index.js',   // 单入口文件,路径跟名字是可以自己随意修改
        },
        output: {
          filename: 'main.js',   // filename 是填写自己的文件名,也可以直接用[name].js
          path: path.resolve(__dirname, 'dist')  // path:需要填写路径。path.resolve()是nodejs的代码合并。__dirname是当前目录路径。'dist' 是根目录下的dist文件名。
        }
        ···
      };
    
    1. 配置多出口文件
      const path = require('path');
      module.exports = {
        entry: { // 多入口文件需要以数组的形式传入
          'index': ['./src/index.js'], 
          'modu': ['./src/modu.js'],
        },
        output: {
          filename: '[name].js',  // 如果是多出口文件,名字必须是[name].js
          path: path.resolve(__dirname, 'dist')
        }
      };
        ···
      };
    
    1. 公共代码,私有代码分离

    如果你使用了多入口打包文件,在两个js文件里引入的同一个文件,这个时候就会重复打包js文件,为了避免重复打包需要改一下配置:

      const path = require('path');
    
      module.exports = {
        entry: {  // index.js和modu.js 都引用了同一个jquery.js   (import $ from 'jquery';)
          'index': ['./src/index.js'],
          'modu': ['./src/modu.js'],
        },
        output: {
          filename: '[name].js',
          path: path.resolve(__dirname, 'dist')
        },
        optimization: {
          splitChunks: {
            cacheGroups: {
              vendor: { // vendor名字随意取都可以
                test: /node_modules/, // 匹配相应文件夹下的模块
                chunks: "all",   // 匹配的块的类型:initial(初始块),async(按需加载的异步块),all(所有块)
                name: "main",    // 输出的js名字,可以随意修改
                priority: 10,  // 设置优先级,分离规则的优先级,优先级越高,则优先匹配
                enforce: true,
                minChunks :2  // 分离前,该块被引入的次数
              }
            }
          }
        }
      };
    

    打包出来后。可以在dist看到3个js。分别是index.js,main.js,modu.js

    1. 插件代码,配置下载第三方库
    • 直接npm下载,然后引入,这样会有一个问题,如果每个页面都需要使用的话,就需要在每一个每页都手动引用,太麻烦
    import $ from 'jquery';
    const b = '2'
    $('body').append(b);
    
    • ProvidePlugin配置,全局配置,一次管够
    const webpack = require('webpack');
    
    plugins:[
        new webpack.ProvidePlugin({
            $:'jquery'  //下载Jquery库
        })
    ]
    
    代码缓存

    浏览器缓存机制,在很多时候,我们需要清除缓存,最直接的办法就是修改文件引用路径,所以在打包出来的文件名添加哈希值,修改上面配置:
    用下面几种方法配置:
    [hash] ---- 模块标识符(module identifier)的 hash
    [chunkhash] ---- chunk 内容的 hash
    [id] ---- 模块标识符(module identifier)
    [query] ---- 模块的 query,例如,文件名 ? 后面的字符串
    [contenthash] ---- 自己模块的内容变化,那么hash值才改变

      const path = require('path');
    
      module.exports = {
        entry: {
          'index': ['./src/index.js'],
          'modu': ['./src/modu.js'],
        },
        output: {
          filename: '[name].[chunkhash].js',  // 添加hash值
          path: path.resolve(__dirname, 'dist')
        },
        optimization: {
          splitChunks: {
            cacheGroups: {
              vendor: { // vendor名字随意取都可以
                test: /node_modules/, // 匹配相应文件夹下的模块
                chunks: "all",   // 匹配的块的类型:initial(初始块),async(按需加载的异步块),all(所有块)
                name: "main",    // 输出的js名字
                priority: 10,  // 设置优先级,分离规则的优先级,优先级越高,则优先匹配
                enforce: true,
                minChunks :2  // 分离前,该块被引入的次数
              }
            }
          }
        }
      };
    

    打包出来后,我们可以看到到文件名发生变化了

    环境配置(模式配置)

    webpack 增加了模式区分,有生产环境和开发环境两种打包方式

    • development:开发模式,打包默认不压缩代码,默认开启代码调试
    • production:生产模式,上线时使用,打包压缩代码,不开启代码调试。
    1. 通过在配置文件中添加mode配置项进行模式选择
      module.exports = {
        mode: 'development',
      };
    
    1. 通过配置package.json文件 进行模式切换:
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start": "webpack --config webpack.config.js --mode production",  // 生产模式
        "start:dev": "webpack --config webpack.config.js --mode development" // 开发模式
      },
    
    编译代码

    把es6+ 的代码转义成es5的代码,解决浏览器兼容问题,需要下载Babel-loader来实现
    webpack4 + 下载:

    npm install -D babel-loader @babel/core @babel/preset-env
    

    添加 babel-loader 到 module 的 loaders 列表中

      module.exports = {
        module: {
          rules: [{
            test: /\.js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-env']
              }
            }
          }],
        },
      };
    

    html打包

    打包html需要下载html-webpack-plugin插件:

    npm install html-webpack-plugin --save-dev
    

    在webpack.config.js文件引用插件

    const HtmlWebpackPlugin = require('html-webpack-plugin')
     module.exports = {
        ···
        plugins: [
          new HtmlWebpackPlugin({
            filename: 'index.html',  // 默认储存到dist文件夹目录下
          }),
        ]
        ···
    }
    
    

    如果需要引入模板:

    const HtmlWebpackPlugin = require('html-webpack-plugin')
     module.exports = {
        ···
      module: {
        rules: [
          {
            test: /\.html$/,
            use: [ {
              loader: 'html-loader',
              options: {
                minimize: true
              },
            }],
          }
        ]
      },
        plugins: [
          new HtmlWebpackPlugin({
            filename: 'index.html', // 默认储存到dist文件夹目录下
            template: 'index.html', // 添加html模板
            cache: false, // 清除缓存
            hash: true   // 添加哈希值
          }),
        ]
        ···
    }
    
    

    指定引入多出口的js文件:

    const HtmlWebpackPlugin = require('html-webpack-plugin')
     module.exports = {
        ···
        plugins: [
          new HtmlWebpackPlugin({
            filename: 'index.html', // 默认储存到dist文件夹目录下
            template: 'index.html', // 添加html模板
            cache: false, // 清除缓存
            hash: true,   // 添加哈希值
            chunks: ['modu'] // 值与entry中的key对应
          }),
          new HtmlWebpackPlugin({
            filename: 'modu.html', // 默认储存到dist文件夹目录下
            template: 'modu.html', // 添加html模板
            cache: false, // 清除缓存
            hash: true,   // 添加哈希值
            chunks: ['modu'] // 值与entry中的key对应
          }),
        ]
        ···
    }
    
    

    css独立打包

    npm install mini-css-extract-plugin --save-dev
    
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    module.exports = {
      module: {
        rules: [{ // 加载样式
            test: /\.(sa|sc|c)ss$/,
            use: [{
                loader: MiniCssExtractPlugin.loader,
              },
              'css-loader',
            ],
          },
        ]
      },
      plugins: [
        new MiniCssExtractPlugin({
          filename: 'asset/css/index.css',   // 指定出口
        }),
      ],
    };
    

    字体打包

    
      module: {
        rules: [
          { // 加载字体
            test: /\.(woff|woff2|eot|ttf|otf|svg)$/,
            loader: 'file-loader',
            options: {
              name: '[name].[contenthash:8].[ext]', // name:文件名,contenthash:哈希,:8:哈希的长度吗,[ext]:文件后缀
              outputPath: 'asset/fonts/', // 打文件打包路径
            },
          },
        ]
      },
    

    图片打包

      module: {
        rules: [
          { // 加载图片
            test: /\.(png|jpg|gif)$/,
            loader: 'file-loader',
            options: {
              esModule: false, // 这里设置为false
              name: '[name].[contenthash:8].[ext]', // name:文件名,contenthash:哈希,:8:哈希的长度吗,[ext]:文件后缀
              outputPath: 'asset/img/', // 打文件打包路径
            },
          },
        ]
      },
    
    

    资源文件如果打包时,路径不统一可以使用绝对路径:

    module.exports = {
      output: {
        publicPath: 'http://localhost:7788/', // html模板里的img图片前缀
      },
    }
    

    若要开启代码调试可在配置文件中增加devtool配置项

    devtool: "source-map"
    

    开发中 Server(代码热更新)

    npm install webpack-dev-server --save-dev
    
    // webpack.config.js 文件配置
    module.exports = {
        devServer: {
          contentBase: path.join(__dirname, "dist"),
          compress: true,
          port: 9000,
          open: true
        }
      }
    
    // package.json文件配置
      "scripts": {
        "start:dev": "webpack-dev-server"
      },
    

    vue 常见问题

    打包vue代码的时候出现如下报错:You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders

    答:处理文件链接:https://vue-loader.vuejs.org/zh/guide/#vue-cli

    vue引入插件方法

    安装:

    npm install xxxx --save
    
    // main.js中引入:
    import yyy from 'xxxx'
    Vue.use(yyy)
    

    相关文章

      网友评论

          本文标题:webpack4+ 基础配置及使用

          本文链接:https://www.haomeiwen.com/subject/gnpmbctx.html