webpack5 实现项目工程化

570 阅读6分钟

现代前端开发遇到的问题

  • 采用模块化开发
  • 使用新特性提高效率保证安全性
  • 实时监听开发过程使用热更新
  • 项目结果打包压缩优化

什么是 webpack

  • 为现代 JavaScript 应用提供静态模块打包工具

webpack 功能

  • 打包: 将不同类型资源按模块处理进行打包
  • 静态: 打包后最终产出静态资源
  • 模块: webpack 支持不同规范的模块华开发

webpack 基本使用

  • 项目初始化 npm init -y
  • 安装 webpack webpack-cli, yarn add webpack webpack-cli
  • 创建 src 路径
  • 创建 index.html 用于将来展示内容
  • 在 src/js/utils.js 写入 es6 等 高阶语法
const sum = (m, n) => {
    return m + n
}

const square = (m) => {
    return m * m
}

export { sum, square}
  • 在 src/index.js 通过import 语法进行导入
import {sum, square} from './js/utils.js'

console.log(sum(10, 20));
console.log(square(10));
  • 在 /index.html 下 引入index.js文件

截屏2021-09-01 下午11.54.55.png

  • 此时在浏览器中通过 live-server 打开 index.html 会发现报错

截屏2021-09-01 下午11.51.05.png

  • 错误的原因是因为浏览器 不支持 ES6 导出规则
  • 解决办法就是在 script 标签中 加上 type=“module” 属性

到这里就解决了我们 ES6 导入模块的问题了,此时我们想,既然解决了这个问题那我们还需要 webpack 解决什么呢

此时,如果有其他的小伙伴在他的js中 使用了 CommonJS 规则的话,那就不一样了

  • 在 js/api.js中 使用 commonjs 规则进行 模块导出
const getInfo = () =>{
    return {
        name: 'zoe',
        age: 40
    }
}

module.exports = getInfo
  • 在index.js 中引入 js/api.js 文件
import {sum, square} from './js/utils.js'
const getInfo = require('./js/api')

getInfo()

console.log(sum(10, 20));
console.log(square(10));
  • 此时,浏览器又报错了,因为浏览器也不支持CommomJS规则

截屏2021-09-02 上午12.09.28.png

  • 怎么解决呢,此时就用到了我们的 webpack,在我们的项目文件中 执行 yarn run webpack, 就会在我们项目中生成一个dist 目录,这里存放着我们webpack处理好的文件

截屏2021-09-02 上午12.14.09.png

  • 在我们的 index.html 中引入我们处理好的 dist/main.js, 此时在浏览器中就解决了我们之前导入规范的报错

webpack配置

打包入口

  • webpack 打包默认会找到 src/index.js 作为打包入口文件
  • 如果想修改打包入口
    • 第一种就是在执行webpack时 追加执行文件路径 yarn run webpack --entry ./src/main.js
    • 第二种通过webpack 配置文件中的 entry 属性设置

打包出口

  • 如果想修改打包出口
    • 第一种就是在执行webpack时,追加输出路径 yarn run webpack --output-path ./build
    • 第二种通过webpack 配置文件中的 output 属性设置

webpack 配置文件 webpack.config.js

  • 注意
    • 打包入口 可以是相对路径
    • 打包出口 必须是个绝对路径
const path = require('path')
module.exports = {
    entry: './src/index.js',    // 打包入口
    output: {                   // 打包出口
        filename: 'build.js',   // 输出文件名称
        path: path.resolve(__dirname, 'dist')  // 输入文件路径, 注意这里必须是个绝对路径
    }
}

loader 的使用

为什么要 loader

因为我们 webpack 只能识别js代码,其他格式代码 webpack 识别不出来,所以需要loader 进行代码的转换

loader是什么

就是一个帮助 webpack 识别非js代码的模块

css-loader 的使用

  • 创建 src/login.js文件,在于模仿登陆组件向页面中追加一个DOM元素
function login () {
    const H2 = document.createElement('h2')
    H2.innerHTML = '测试loder 的使用'
    H2.className = 'title'
    return H2
}

document.body.appendChild(login())
  • index.js 中引入我们的login.js文件,因为如果不在入口中引入该文件,webpack就不会将该文件作为我们打包的模块
import './js/login'
  • 在项目中创建src/css/login.css文件,对我们的 login.js 中的DOM进行样式修改
.title {
    color: pink;
}
  • 在login.js 中引入我门的login.css,这样在执行 webpack 构建时,webpack 会找到 index.js, index.js 中引入了 login.js, login.js 中有引入了 login。css, 这样就形成了相互依赖的关系,webpack 就会自己找到依赖的对应文件了
+ import '../css/login.css'

function login () {
    const H2 = document.createElement('h2')
    H2.innerHTML = '测试loder 的使用'
    H2.className = 'title'
    return H2
}

document.body.appendChild(login())
  • 此时执行 webpack 打包,但是此时出现错误,因为我们webpack 只能识别js 模块,其他模块是识别不出来的,所以要引入对应的loader 来执行对应的模块

01.png

  • 安装 css-loader yarn add css-loader
  • 添加 css-loader
    • (webpack5 建议使用 行内 loader的加载方式)
// login.js
import 'css-loader!../css/login.css'

function login () {
    const H2 = document.createElement('h2')
    H2.innerHTML = '测试loder 的使用'
    H2.className = 'title'
    return H2
}

document.body.appendChild(login())

    • 或者在配置文件中使用 loader
const path = require('path')
module.exports = {
    entry: './src/index.js',    // 打包入口
    output: {                   // 打包出口
        filename: 'build.js',   // 输出文件名称
        path: path.resolve(__dirname, 'dist')  // 输入文件路径, 注意这里必须是个绝对路径
    },
    module: {
        rules: [
            {
                test: /\.css$/, // 一般就是一个正则表达式,用于匹配我们需要处理的文件类型
                use: [{
                    loader:'css-loader',
                    // options: 
                }], // 
            },
            // 简写形式
            {
                test:/\.css$/,
                loader: 'css-loader'
            }
             // 简写多个loader形式
            {
                test:/\.css$/,
                loader: [css-loader]
            }
        ]
    }
}
  • 此时就解决了我们webpack 打包是报错, 但是我们页面上仍然还是没有样式的现实,因为我们cdd-loader 只是将 css代码 让webpack识别出来,但是还是没有应用,此时就需要style-loader 让我们的css 效果显示出来

style-loader的使用

  • 安装 style-loader yarn add style-loader
    • 注意 loder 的执行顺序是从又往左执行
const path = require('path')
module.exports = {
    entry: './src/index.js',    // 打包入口
    output: {                   // 打包出口
        filename: 'build.js',   // 输出文件名称
        path: path.resolve(__dirname, 'dist')  // 输入文件路径, 注意这里必须是个绝对路径
    },
    module: {
        rules: [
            {
                test: /\.css$/, // 一般就是一个正则表达式,用于匹配我们需要处理的文件类型
                use: [ 'style-loader','css-loader'], // 
            }
        ]
    }
}

less-loader 的使用

  • yarn add less less-loader
  • 在webpac配置文件中增加对应的loader
const path = require('path')
module.exports = {
    entry: './src/index.js',    // 打包入口
    output: {                   // 打包出口
        filename: 'build.js',   // 输出文件名称
        path: path.resolve(__dirname, 'dist')  // 输入文件路径, 注意这里必须是个绝对路径
    },
    module: {
        rules: [
            {
                test: /\.css$/, // 一般就是一个正则表达式,用于匹配我们需要处理的文件类型
                use: [ 'style-loader','css-loader'], // 
            },
+           {
+                test: /\.less$/,
+                use:['style-loader','css-loader','less-loader']
+            }
        ]
    }
}

  • 此时我们的 webpack 就能执行 less 语法了

browserslistrc 工作流程

为什么会有 browserslist

  • 因为现代前端都是模块化开发,要处理各种浏览器的兼容性
  • 如何兼容,要兼容那些平台,现在浏览器兼容占比在 can i use https://caniuse.com/, 这个网站已经统计好了,而 browserslist 这个插件会自动的去查找当前各种浏览器占比,
  • 我们在项目中 安装 browserslistrc yarn add browserslistrc
  • 执行 yarn run browserslistrc 会显示出当前浏览器所占比, 在正式的项目当中,browserslistrc 已经配置好了,不需要我们做什么,只是在当前看一下当前占比
  • 可以在pacakage.json 中简单的配置一下浏览器兼容占比
{
    "browserslistrc": [
        "> 1%",
        "last 2 version",
        "not dead"
  ]
}
  • 也可以在单独的配置文件
> 1%
last 2 version
not dead

postcss 工作流程

  • browserslistrc 筛选出要兼容的平台,postcss就可以进行兼容性产出了
  • postcss 是什么呢,可以理解为是 通过 JavaScript 转换样式的工具

postcss 的使用

  • 安装postcss yarn add postcss postcss-cli -D
  • 创建一个test.css 文件,为了验证 postcss 是否会给我们自动加上浏览器前缀
  • autoprefixer.github.io/ 这个网站记录这一些css 浏览器兼容问题的样式
// test.css
.title {
    display: grid;
    transition: all .5s;
    user-select: none;
    background: linear-gradient(to bottom, white, black);
}
  • 在index.js 中引入test.css
import '../css/test.css'
  • 执行命令 % yarn run postcss -o rest.css ./src/css/test.css, 会在当前目录下生成 rest.css 文件,但是你会发现 这个文件内,只是单纯的将 test.css 文件全部拷贝过来了,没有任何的处理
.title {
    display: grid;
    transition: all .5s;
    user-select: none;
    background: linear-gradient(to bottom, white, black);
}

/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9jc3MvdGVzdC5jc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7SUFDSSxhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLGlCQUFpQjtJQUNqQixvREFBb0Q7QUFDeEQiLCJmaWxlIjoicmVzdC5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyIudGl0bGUge1xuICAgIGRpc3BsYXk6IGdyaWQ7XG4gICAgdHJhbnNpdGlvbjogYWxsIC41cztcbiAgICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQodG8gYm90dG9tLCB3aGl0ZSwgYmxhY2spO1xufVxuIl19 */
  • 但是单独的 postcss 是不能完成样式兼容性处理的,因为他还需要 Autoprefixer 配合处理, 所以要安装 yarn add Autoprefixer -D

  • 此时执行 yarn run postcss --use autoprefixer -o rest.css ./src/css/test.css, rest.css 就会添加上浏览器前缀

.title {
    display: grid;
    transition: all .5s;
    -webkit-user-select: none;
       -moz-user-select: none;
        -ms-user-select: none;
            user-select: none;
    background: linear-gradient(to bottom, white, black);
}

/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNyYy9jc3MvdGVzdC5jc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7SUFDSSxhQUFhO0lBQ2IsbUJBQW1CO0lBQ25CLHlCQUFpQjtPQUFqQixzQkFBaUI7UUFBakIscUJBQWlCO1lBQWpCLGlCQUFpQjtJQUNqQixvREFBb0Q7QUFDeEQiLCJmaWxlIjoicmVzdC5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyIudGl0bGUge1xuICAgIGRpc3BsYXk6IGdyaWQ7XG4gICAgdHJhbnNpdGlvbjogYWxsIC41cztcbiAgICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQodG8gYm90dG9tLCB3aGl0ZSwgYmxhY2spO1xufVxuIl19 */