webpack学习(一)基础用法

wbepack4

webpack是一款模块打包器,可以解决前端工程化中引入依赖资源等一些列问题

start启动打包

每一个webpack工程都要有一个或多个配置文件默认是webpack.config.js,我们也可以执行命令webpack --config [name].js来执行自定义文件名的配置文件,在文件中我们使用commonjs规范导出我们的配置参数例如下边这个简单的事例,其实就是webpack会根据我们导出的对象来解析合并一些默认配置来打包各个资源,webpack4中为了简化我们的开发增加大量的默认配置

module.exports = {
  entry:'index.js'
}

entry入口

我们打包文件都要有一个入口文件,就是我们要以一个入口文件开始递归的将依赖的资源全都打包到一起我们看一下基本的配置,和一个最简单的demo,我们使用es6的模块化方式来加载模块,这在浏览器中是不被识别的,我们执行npx webpack命令,默认打包输出在./dist目录下,我们定义入口的key就是我们生成文件的名字,我们看一下打包输出信息。

webpack-entry.png

  • 打包多文件我们可以定义多个入口,这也是多页面打包常用的方法
  • 我们也可以将入口传入的文件路径改成一个数组,这样会将多个入口文件的依赖打包成一个文件,这也是我们在实践中常用的将一些第三方依赖打包在一起的方法
// webpack.config.js
module.exports = {
  entry:{
    main: 'index.js',
  }
}
// index.js
import Header from './header';
import Content from './content';

Header();
Content();

// header.js
function Header(){
  const root = document.getElementById('root');
  const header = document.createElement('header');
  header.innerText = 'header';
  root.appendChild(header);
}

export default Header

//content.js
function Content(){
  const root = document.getElementById('root');
  const content = document.createElement('content');
  content.innerText = 'content';
  root.appendChild(content);
}

export default Content

output

上边定义文件打包的入口,我们可以定义output参数来定义我们打包的生成目录地址,我们可以使用占位符来定义我们生成文件的名字,也可以定义路径及我们将文件上传cdn后自动给我们加上域名前缀

module.exports = {
  entry: {
    main: path.join(__dirname, './src/index.js'),
  },
  output:{
    filename: '[name]-[hash].js', // 占位符定义输出名称
    path: path.join(__dirname, "./build"), // 输出的文件夹
    publicPath: 'http://www.xxx.com' // 文件上传cdn的公共前缀
  }
}

loader加载器

我们可以利用webpack来打包各种资源就是依赖于loader,我们可以对各种类型的文件采用不同的方式生成bundle模块,webpack默认只会给我们加载js文件,剩下所有类型的文件都需要我们自己来处理。
我们来使用一个module属性中添加一条rules规则,常用test来匹配文件后缀,use来指定使用的loader,可以是一个字符串或者数组,数组表示我们将利用链式规则处理这种资源文件

css-loader

我们来看一个例子,我们在入口文件引入一个css文件如果我们不对css文件增加loader,默认是打包失败的,提示我们应该添加一个loader来处理这种文件,我们添加了2个loader来处理css文件,style-loader表示我们将处理好的css文件插入到js文件的head中,css-loader是真正用来解析css文件的。

import Header from './header';
import Content from './content';
import './css/index.css';

Header();
Content();

// webpack.config.js
module.exports = {
  module:{
    rules: [
      {
        test: /\.css$/,
        use: [
          {loader: 'style-loader'},
          {
            loader: 'css-loader'
          }
        ]
      }
    ]
  }
}

在工程实践中,我们像上边这样使用会有些问题,我们在全局引入可能会有样式重名,css样式庞大之后各种css权重优先级的问题,在webpack中已经给我们提供了解决方案,我们只需要在css-loader中新增加一个配置项,像下边这样,添加options为true这样在引入css时,我们将css导出给一个变量,这样在页面中css会生成一个基于md5的css名称解决了重名的问题

module.exports = {
  module:{
    rules: [
      {
        test: /\.css$/,
        use: [
          {loader: 'style-loader'},
           {
            loader: 'css-loader',
            options: {
              modules: true
            }
          }
        ]
      }
    ]
  }
}
// header.js
import css from './css/header.css'

function Header(){
  const root = document.getElementById('root');
  const header = document.createElement('header');
  header.className = css.title
  header.innerText = 'header';
  root.appendChild(header);
}

url-loader

我们在加载一些静态资源时可以使用file-loader来帮我们打包文件,常用来加载图片会使用这个url-loader,可以为我们将小图片转为base64编码

module.exports = {
  module:{
    rules: [
       {
        test: /\.(jpg|png)$/,
        use: {
          loader: 'url-loader',
          options:{
            limit: 10240, // 小于大小限制的图片转为base64
          }
        }
      }
    ]
  }
}

plguins插件

我们在打包过程中会使用插件帮我们做上边无法实现的一些功能,先来简单介绍一下,我们定义在plugins属性中,我们在打包时都是以js文件为入口我们要显示页面最终都要将js插入到html中,如果我们都等打好包后,再修改引入文件的名称是一件很麻烦的事,我们可以使用插件来帮我们完成这件事,我们使用生成的js经常是将代码拆入到一个跟标签中,所以我们可以定义一个template属性来指定html的模版,会在output的目录为我们生成一个html并将js都拆入好

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, './index.html')
    })
  ]
}

source-map

我们使用devtool属性来配置source-map,webpack帮我们打包了代码,我们在开发中需要调试代码,在mode为development默认会为我们开启inline-source-map,也就是我们打包前的文件与打包后生成代码的映射关系,所以当代码出错时我们可以在对应的行数找到我们的代码,在mode为production时会为我们设为none来减少我们打包我们代码的体积,关于这个字段有很多配置项可以去官网上查看,基于最佳实践,在开发模式下我们使用cheap-module-eval-source-map这样会为我们保持原有代码并且rebuid速度也快

webpack-dev-server

在之前我们每次修改了代码我们都需要手动build一遍代码这样很不方便,webpack官方给我提供了内置的属性devServer来实现开发模式自动重新build功能,会监听文件的变化然后自动为我们打包刷新页面

module.exports = {
  devServer: {
    contentBase: './build', // 将这个目录下的文件允许在端口下访问
    port: 8000, // 设置访问端口
    open: true, // 自动为我们打开浏览器
  },
}

我们看看来实现一个简单的devServer服务,我们需要先安装express和webpack-dev-middleware,webpack-dev-middleware可以将监听文件的修改然后将文件重新打包传给node服务,我们启动node devServer.js在3000端口就能实现和devServer看起来一样的功能,webpack-dev-server还有很多高级功能不是这么简单,这也是webpack运行在node端的一种实现

// devServer.js
const express = require("express");
const WebpackDevMiddleware= require("webpack-dev-middleware");
const webpack = require("webpack");
const config = require("./webpack.config.js");

const app = express();
const compiler = webpack(config); // 编译代码

app.use(WebpackDevMiddleware(compiler)) // 将打包好的代码交给服务器

app.listen(3000, () => {
  console.log("server is start")
})

HMR热更新

在开发中我们dev-server中帮我们实现了重新打包的功能,但我们在开发时我们想实现不刷新,维持浏览器现有状态更新代码,我们需要这样更新配置,将devServer中hot设为true并加入热更新插件,当我们这样配置完成后引入的css可以自动完成热更新,这样因为css-loader已经帮我们编写了热更新代码,对于js文件我们要自己监听文件的变化,当文件变化时我们要自己处理如何去热更新代码,在react,vue中社区已经

module.exports = {
  devServer: {
    contentBase: './build', // 将这个目录下的文件允许在端口下访问
    port: 8000, // 设置访问端口
    hot: true,
  },
  plugins: [
    new webpack.NamedModulesPlugin(),
    new webpack.HotModuleReplacementPlugin()
  ]
}

// index.js
if(module.hot){ // 判断是否开启热更新
  module.hot.accept("./header.js", () => { // 监听文件是否变化,变化执行回调函数
    Header();
  })
}

babel代码转换

在我们编写代码时我们经常会使用es6的语法,chrome浏览器能识别,但有些浏览器或手机浏览器不能识别这些高级语法,我们需要将代码转换成在哪里都可以运行的代码就要借助babel了,写.jsx文件时我们,我们也需要将代码转化浏览器能识别的我们借助的也是babel来帮我编译我们先看一下基础的配置,我们可以按照官网的配置先安装几个依赖 npm install --save-dev babel-loader @babel/core @babel/preset-env npm install --save @babel/polyfill。我们忽略的node_modules文件夹中的文件,使用babel-loader来处理js,我们还要定义我们要使用什么规则来处理,我们在入口文件引入import "@babel/polyfill";来在window下帮我们生成一些hock语法.

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

// .babelrc
{
  "presets": [
    [
      "@babel/preset-env"
    ]
  ]
}

像上边这样使用我们会将整个polyfill文件都打包到我们的文件中,官方给我提供了一个参数可以来实现按需打包的配置如下,这样可以将我们的包体积减小很多,当我们这样配置时,我们可以不用在代码里引入polyfill文件,会自动为我们引入

// .babelrc
{
  "presets": [
    [
      "@babel/preset-env",{
        "useBuiltIns": "usage"
      }
    ]
  ]
}

我们可以添加targets参数来指定我们打包浏览器的版本,这样会只能给我们将polyfill的代码打包进去

如果我们只是在业务中使用babel这样没有问题,但我们在开发类库的时候,会在window上污染全局变量,babel也给我们提供了解决方案npm install --save-dev @babel/plugin-transform-runtime npm install --save @babel/runtime,这样就不会污染我们的全局变量

{
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "absoluteRuntime": false,
        "corejs": 2,
        "helpers": true,
        "regenerator": true,
        "useESModules": false
      }
    ]
  ]
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容

  • webpack使用学习 本分享学习借鉴webpack中文官网,官网链接(中文文档):https://www.web...
    腿毛怪丶叔叔阅读 863评论 0 5
  • 全局安装webpack 全局安装webpack会有个问题,就是当你有两个项目依赖于不同版本的webpack,就会有...
    説好的妹紙呢阅读 1,799评论 0 11
  • 写在开头 先说说为什么要写这篇文章, 最初的原因是组里的小朋友们看了webpack文档后, 表情都是这样的: (摘...
    Lefter阅读 5,266评论 4 31
  • 目录第1章 webpack简介 11.1 webpack是什么? 11.2 官网地址 21.3 为什么使用 web...
    lemonzoey阅读 1,730评论 0 1
  • 4年光阴,我与你从遇见,到相识,到相爱,再到如今爱的很辛苦,我越来越累,越来越焦虑,连梦里都是泥泞的,我想,你我的...
    海边的蓝兔子阅读 148评论 0 3