Webpack入门配置指南

917 阅读11分钟

前置知识

  • ES6的使用

let / const/箭头函数/... / new / class / Promise

继承/this/原型

  • CSS语法和布局

  • MVC概念

Model /View / Controller / EventHub

  • 工具的使用

VSCode或 WebStorm

终端命令行npm / yarn / http-server / parcel / git

  • 源码

webpack配置源码地址: github.com/woshidw/web…

--资料来源于饥人谷

正式进入框架阶段

进入之前,了解一些工具。

可以按照CRM安装一些工具,也可以用我推荐的用法

本文用的

  "devDependencies": {
    "webpack": "^5.24.2",
    "webpack-cli": "^4.5.0",
  }

Webpack是什么

这玩意是干什么的?

  • 转译代码(ES6转为ES5,SCSS 转为CSS)

  • 构建build

  • 代码压缩

  • 代码分析

说那么多,不如直接干

用CRM(Copy,Run,Modify)学习法搞定所有新知识

实现的webpack配置流程

下面将用一步步实现8个目标来完成配置流程

分别是用webpack 转译JS,理解hash的用途生成HTML引入CSS引入scss引入less和stylus引入图片实现懒加载,点击可到对应模块。

CRM学(抄,运行,改) webpack

每次完成一个目标配置可以先把代码提交一哈,防止配崩了

环境搭配

全局安装,也可以不安,我全局和局部都安了

  • 全局安装
npm i -g webpack@版本号 webpack-cli@版本号
//@后面加版本号

//或者npm:
npm i -g webpack webpack-cli
// 或者yarn:
yarn global add webpack webpack-cli

怎么看版本 使用npm info webpack查看webpack所有信息,webpack3本身和它的cli以前都是在同一个包中,但在第4版以后中,他们两个是分开的。

版本不对容易导致一些看不懂的版本错误,我全局和局部都是一个版本

学习方法,途径

学习方法:

进入 webpack官网

使用CRM来学习

  • 使用教学

进入官网 webpack.js.org/

找到ducument导航栏GUIDES--》getting started入门指南

然后抄,运行,改。下文也会写到相对应的地方进行CRM。前端更新迭代快,webpack没有一个固定的配置,有时候也需要根据需求进行配置,所以CRM学习,掌握方法显得尤为重要。


目标一——用webpack 转译JS

(把JS变成能够在所有浏览器运行的JS)

安装的所有依赖都是本地安装--dev,因为webpack的东西用户是用不到的

好了,正式开始配置

  1. 创建一个文件webpack-demo-1,用vs打开,

  2. 在vs打开终端输入npm init -y初始化配置

或者用命令行创建并进入

mkdir webpack-demo
cd webpack-demo
npm init -y

初始化后你会发现文件里多了个package.json

  1. 然后添加依赖在本地局部安装webpack,用yarn add webpack webpack-cli --dev或者npm install webpack webpack-cli --save-dev。

我这里用本地安装yarn add webpack webpack-cli --dev

我的版本号是

  "devDependencies": {
    "webpack": "^5.24.2",
    "webpack-cli": "^4.5.0"
  }

安装完后会多个node_modules目录

  1. 看版本./node_modules/.bin/webpack --version因为是局部安装,所以要这样查看,调用本地的webpack也这样调用

或者使用简单用法npx webpack(npx会自动在本地查找在哪里,不用再写那么多)但是npx不稳定(比如在windows装node装到了到了带空格的目录,npx就不能用了,只能退回手动输入的,我这里装node没问题,所以用npx webpack)

  1. 然后创建src目录下index.js文件,输入一些简单的代码,比如console.log('hi')

运行npx webpack--然后转译js

有个警告,先不管,下面会去警告

运行后我们发现,多了个dist目录,里面有main.js。这就是index.js里的console.log('hi')通过webpack转译的js。--这是webpack自带的转译js功能,不需要安装loader和plugin。

那能不能使一些复杂的js转译呢?

引入当前目录下的x.js文件

import x from './x.js'
console.log('x')
  1. src目录下创建x.js,导出xxxexport default 'xxx'

index.js里的代码是不能直接在浏览器上运行的

  1. 然后用npx webpack或者./node_modules/.bin/webpack(本地)来转译js,会创建dist/main.js文件。

这里webpack会分析代码,把代码变成浏览器可以用的。

里面代码是不是不一样。至此第一个小目标转译js完成

附加:转译过程中去警告(mode模式)

警告就是上面目标1里的警告,虽然警告没什么问题,但看着就是不爽

复制一段警告面向google学习

在webpack官网入门指南里configration。找不到可以ctrl+f查找

创建和src同级别webpack.config.js文件,警告说mode没有被设置,那在里面加入以下代码

const path = require('path');

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

mode是用来切换模式的。可以设置mode是选择(main.js)是development(给开发者看的)还是production(用户看的,最小化,无注释),可以不同设置一下,再运行看看main.js的不同。如果是正在开发中,可以切换成development,如果要发布可以切换为production

这是重新运行npx webpack的结果-没有警告


目标二——理解文件名中的hash的用途

hash用途是用来便于添加缓存的,这个缓存是http协议规定的,浏览器必须自动支持。

(CRM学webpack)

目标一去警告配置里的代码

module.exports = {
    mode: 'development',
    entry: './src/index.js', //默认入口文件
    output: {//输出
      path: path.resolve(__dirname, 'dist'),//默认定位,文件的目标路径
      filename: '[name].js', //。[name]可以改。
      //filename: 'index.[contenthash].js', //输出文件。缓存配置hash,方便更新。[name]我这里改成index
  },
};
//总的意思是默认把src下的index.js转译后放到dist下的main.js

entry(入口)和output(出口)把src下的index.js转译之后当到dist的main.js。[name]可以改。可以搜索webpack filename hash看缓存配置,把output文件名改为了[name].[contenthash].js

每次运行webpack的话dist里的文件不会越来越多么?运行webpack之前删掉distrm -rf dist; npx webpack,但要是忘了怎么办,有个功能,在pakage.json里的scripts添加(这里npx可以省略,因为会默认去找webpack)

"build" : "rm -rf dist && webpack",

那么,每次需要打包的时候,直接运行yarn build或者npm run build

附加知识:http缓存-设置缓存头Cache-Control

什么是http缓存呢,举例说明

第一次访问baidu.com,返回index.html,index.html会引入下载一些css,js文件。把这些引入的文件放入缓存里,比如放缓存里一年不会改。(如何更新?)

第二次访问baidu.com的时候,只需要下载index.html,然它会去从内存里得到css,js文件,这样就实现了超快访问。(为什么index.html不缓存?)

  • 假如要更新一个css怎么办呢,如何更新?

因为缓存是跟着文件名走的,所以只需要一下文件名就好了,怎么改文件名呢,对文件内容作一个hash filename: 'index.[contenthash].js', (只要文件内容不一样,(文件名和文件内容有一一对应关系)通过webpack发布后,这样浏览器就知道是否更新了,以前的缓存就不能要了,需要重新请求新的),webpack就会自动做这种事情

  • 为什么index.html不缓存呢?

。。首页缓存了浏览器还怎么知道css那些更新了没有。


目标三——用webpack生成HTML

要点:自动改文件名,自动添加script(模板),自动使用配置里的title

如何自动改文件名

搜到官方文档 HtmlWebpackPlugin

按照教程走,安装npm install --save-dev html-webpack-plugin或者yarn add html-webpack-plugin --dev,然后翻到Basic Usage对照webpack.config.js添加

const HtmlWebpackPlugin = require('html-webpack-plugin');//添加
const path = require('path');

module.exports = {
  entry: 'index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'index_bundle.js',
  },
  plugins: [new HtmlWebpackPlugin()],//添加
};

yarn build后 dist里就有index.html了。[name]可以改(我这里改成了index)。

dist里的index.html就自动引入了index.xxxxx.js。如果index.js内容变了,更新后打包,index.html会自动更新地址,加了[contenthash]就不用管文件名了

  • 问题:只有script,想再添加其他标签怎么办?

继续CRM插件文档

比如照着例子:

plugins: [
    new HtmlWebpackPlugin({
      title: 'woshisb',
      template: 'src/assets/index.html'
    }
  )
],

自动添加script,引入模板

src/assets/index.html文件的模板,那就在里面写点东西。yarn build后dist里index.html变成了模板的html并且在合适的地方添加了script,js的入口文件。

自动使用配置里的title

要使用配置里的title的话,就把src/assets/index.html里的title内容改成<%= htmlWebpackPlugin.options.title %>就会使用配置里title: 'woshisb',可以看我的源码

目标四——用webpack 引入CSS

  • 要点:
  1. 可以使用JS生成style

  2. webpack-dev-server调试预览

  3. 也可以把 CSS抽成文件

使用JS生成style

临时用js生成

  • 怎么引入css呢?

创建x.css,写点东西

我直接在x.js引入模块x.css-》error了,把css语法当成js来解释报错了

一样CRM


安装css-loader

yarn add css-loader --dev

webpack.config.js对比抄,

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
};

test 引用.css,$正则表达式(30分钟入门正则表达式)$表示以.css结尾。如果文件名是以.css结尾就使用css-loader和style-loader。此时yarn build依然会报错,哦还没安装style-loader

安装style-loader

yarn add style-loader --dev

安装完成了,cd进入dist用http-server . -c-1命令运行加入路径预览/index.html-》css引入成功(yarn build就关掉服务器),可以看到在head里有一个style标签,里面就是x.css的内容

就是webpake配置弄的,如果发现了任何以.css结尾的文件名,那么就用css-loader去处理这个文件,css-loader会把这个文件的内容读到js里面,style-loader就是把css-loader读到的东西,变成一个style标签放到head里。

每次改完代码都要进入dist,http-server . -c-1,太麻烦了

所以用webpack-dev-server

CRM搜索相应文档找到Using webpack-dev-server

webpack-dev-server是和webpack配套的本地预览,可以实时预览

命令安装

yarn add webpack-dev-server --dev

webpack.config.js配置里mode下面添加

  devServer: {
    contentBase: './dist',
  },

package.json 的script的build上面添加。--open是是否帮你打开浏览器,不需要可以删掉

"start": "webpack serve --open",

然后用yarn start就可以了或者npm run start。访问给出的端口号。这个工具就是当你改代码的时候不用再重新build了,自动帮你搞定,但不会生成dist目录,这是在内存里搞定的。输出html的时候会去读取index.js,然后把index.js转译成可以运行的js,然后把它读到内存里

CSS抽成文件

自动生成+后缀

CRM webpack css extract plugin

安装

yarn add mini-css-extract-plugin --dev

webpack.config.js对照添加,style-loader(放到页面)和MiniCssExtractPlugin.loader(抽成文件)二选一。

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css',
      ignoreOrder: false, // Enable to remove warnings about conflicting order
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              // you can specify a publicPath here
              // by default it uses publicPath in webpackOptions.output
              publicPath: '../',
            },
          },
          'css-loader',
        ],
      },
    ],
  },
};

然后yarn build 可以看到dist里多了个main.css文件,index.html里可以看到对main.css的引用。

但main.css引用没有像引入js那样长的文件名,如何作缓存,main.js会被缓存一年。如何更新它?

在上面修改

new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css',
      chunkFilename: '[id].[contenthash].css',
    }),
  ],

yarn start一下可以看到,head里有一个link标签对css文件的引用,改变x.css里的内容可以实时的生成css然后去引用它

如何在开发的时候用目标1的js临时生成模式,在生产环境build的时候用目标3的抽成文件

生产环境就是要运行build的时候用webpack,开发就是yarn start用serve

代码是这样的

  "scripts": {
    "start": "webpack serve",
    "build": "rm -rf dist && webpack",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

如何做?

复制一份webpack.config.js,叫做webpack.config.prod.js(prod是production的缩写)

默认的webpack.config.js就用做开发时用,用use: ["style-loader", "css-loader"],替换原本的use。

生产环境就用原来的use,可以作缓存。把mode改成production

怎么选择这两个文件呢?

通过命令选

  "scripts": {
    "start": "webpack serve",
    "build": "rm -rf dist && webpack --config webpack.config.prod.js",//build的时候用prod的配置
    "test": "echo \"Error: no test specified\" && exit 1"
  },

可以试验一下,yarn build 后可以看到style标签,yarn start可以看到html文件里link对css的引入

两个文件只有一个地方不一样 --用继承的思想去掉重复代码

新建一个webpack.config.base.js文件

这个文件就把两个文件的共有属性复制过来

可以搜索webpack config merge看别人怎么写的,也可以看我的源代码 --我也是C的

loader与plugin

js文件通过webpack得到一个新的js文件,这是通过webpack内置的一个babel loader,把js loader到webpack里面,webpack就输出一个另外的js。

webpack loader和webpack plugin的区别是什么

webpack loader是用来加载文件的,webpack plugin是用来扩展功能的。

比如babel loader是用来加载高级的js,把它变成ie支持的js,css loader和style loader是用来加载css,把它变成页面中的style标签。功能比较单一

plugin可以用来加强webpack功能用的,功能比较丰富。比如一个插件叫HtmlWebpackPlugin是用来生成html文件的,还有一个叫做MiniCssExtractPlugin是用来抽取css的代码变成一个文件的


目标5——用webpack 引入SCSS

  • 要点

node-sass已经过时

请使用dart-sass

CRM学习webpack scss loader

安装

yarn add sass-loader dart-sass --dev

把css后缀改成scss就可以了,在改下import

添加到webpack.config.base.js。

  module: {
    rules: [
      {
        test: /\.scss$/i,
        use: [
          "style-loader",
          "css-loader",
          {
              loader: "sass-loader",
              options: {
                  implementation: require('dart-sass')
              }
          },
        ],
      },
    ],
  },

目标六——引入 LESS和 Stylus

  • 经验

SASS、LESS、Stylus完全没区别

把css文件后缀改成less就可以变成less文件(声明变量,引用变量),在改下引用

语法

@color: red;
body{
    background: @color;
    color: @color;
}

CRM学习webpack less loader

安装

npm install less less-loader --save-dev

把下面代码对照着添加到rules里

module.exports = {
  module: {
    rules: [
    /* 这里*/
      {
        test: /\.less$/i,
        use: [
          {
            loader: "style-loader",
          },
          {
            loader: "css-loader",
          },
          {
            loader: "less-loader",
            options: {
              lessOptions: {
                strictMath: true,
              },
            },
          },
        ],
      },
      /*到这里*/
    ],
  },
};

创建个z.styl文件,Stylus的后缀就是.styl,记得引入

语法

c = blue;
body{
    background: c;
}

CRM学习 webpack Stylus loader

安装

yarn add stylus-loader stylus --dev

在webpack.config.base.js的rules里添加和上面差不多的代码

module.exports = {
  module: {
    rules: [
    
      {
        test: /\.styl$/,
        use: [
          {
            loader: "style-loader", // creates style nodes from JS strings
          },
          {
            loader: "css-loader", // translates CSS into CommonJS
          },
          {
            loader: "stylus-loader", // compiles Stylus to CSS
          },
        ],
      },
      
    ],
  },
};

目标七——用webpack引入图片

  • 要点

万物皆JS

CRM webpack img loader

添加到rules后面,如果用loader的话就是一张图片引一次。

      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        use: ["file-loader"]//把文件变成文件路径
        // type: 'asset/resource',
      },

安装

yarn add file-loader --dev

index.js里的内容

import x from './x.js'
import png from './assets/1.png'
//import png将由loader决定,png路径会有一串hash
console.log(png)

const div = document.getElementById('app')

div.innerHTML = `
    <img src="${png}">
`

目标八——实现懒加载

什么是懒加载呢,就是该做的时候不做,等到不得不做的时候才做。

为什么要懒加载呢?因为一开始可能某个js文件很大,如果一开始就加载,就要等好久才出现,还不如等用户开启某个模块才用。

如何实现懒加载?用import('xx')去加载一个xx文件,然后会得到一个promise,promise的then前面写成功后做什么,后面写失败做什么。

const button = document.createElement('button')
button.innerText = '懒加载'
button.onclick = ()=>{
    const promise = import('./lazy')
    promise.then((module)=>{
        const fn = module.default()
        fn()
    },()=>{
        console.log('模块加载错误')
    })
}

div.appendChild(button)




配置完成,CRM学习到了么。这也是我CRM老师的。我配置过程中出现过版本错误,老师的配置的webpack4代码和CRM搜到的文档又不一样,经过几次重新配置,最终才配好。我也是才开始学习webpack,其中可能也有很多的不足,但是CRM就行了。

一个前端小白的学习之旅。望共勉。

感谢建议,技术需要严谨