美文网首页工作生活
webpack入坑之路

webpack入坑之路

作者: monkeyying | 来源:发表于2019-09-26 09:55 被阅读0次

Hi ~ 许久没更新的小简书,自从换了新工作,日夜掉发式的疯狂加班,一个半月的时间学到了不少东西,趁热记录一波吧~


程序员病.png

一个月前,接到了一个需求,并且长期需要维护多个无关的活动页或者场景页,自以为简单的我乐呵呵的接了需求,心中已经想好“用react来搭一个多页面应用就够符合需求啦~”,事实证明,我还是too young too simple ,sometimes naive...

自拍照.png

实际开发工作中,react多页面应用的脚手架GitHub上有很多,自己也可以根据官方的react脚手架就可以愉快的撸起来,但是目前遇到的比较头疼的问题是,怎么让我的react应用代码压缩模块打包,这个时候就很有必要好好研究下webpack的使用了。

此次分享主要是针对多页面的webpack4打包。

So,咱们来聊一下,什么是webpack?

官网webpack图

官网上的webpack相信所有前端开发童鞋都见过,webpack做的事情,就是将我们的js应用的各个文件按照模块打包成多个bundle,是一个静态模块的打包器。

webpack做的事情,就是分析项目结构,找到js模块以及一些不能直接运行的语言,并将其打包成合适的格式给浏览器执行。

安装webpack

npm install webpack-cli 

了解webpack前需要知道webpack的四大核心概念,entry、output、loader、plugins。

Entry(入口)

entry是webpack的起点指示,告诉webpack从哪里开始入手打包任务,用来指定入口,默认值是./src。

如果是做单页面程序,单个入口。

//单个入口的写法  entry: string|Array<string>
entry:{
  main:'../src/component/my.js'
}
entry:'../src/component/my.js'
//如果传数组形式,是注入多个入口以及多个依赖文件。

如果是做多个页面,多个入口。

//多个入口的写法,所有的文件会被打包到dist文件中。
entry:{
  app:['./a.js','./b.js','./c.js']
}
//最终输出 dist/a.js   /  dist/b.js   dist/c.js

当webpack在解析代码时,每遇到import或者require引入的依赖,最终会被打包在最终构建结果中。打包的最终结果只会引入该模块引入的依赖。

output(输出)

打包完后输出的位置

output: {
    filename: 'vendor.js',
    path: '/home/index'
  }

loader(加载器)

实际上webpack只能打包js文件,其他资源例如css和html是需要加载器来将资源转化,加载进来。

举个栗子,如果项目中使用了sass的样式语法,是无法被浏览器所识别的,因此需要引用loader,将sass转义成能被识别的css语法阅读。

 {
  test: /\.scss$/,
  use: ['style-loader', 'css-loader', 'sass-loader'],
},    

在该项目中,react用的是jsx的语法,同样无法被浏览器所识别,需要引用babel将jsx语法转义成正常的js运行。

module:{
  rules:[
     {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: [
              "@babel/preset-env",//可以根据配置的目标浏览器或者运行环境来自动将2015+的代码转为es5
              "@babel/preset-react",
              { "plugins": ["@babel/plugin-proposal-class-properties"] }//这句可以在项目中使用箭头函数
            ],
          }
        },
  ]
}

loader的职责是单一的,一个loader相当于一个翻译官,只做翻译某种语言,需要关心输入和输出。
一个项目里有多个翻译官,在调用多个 Loader 去转换一个文件时,每个 Loader 会链式的顺序执行, 第一个 Loader 将会拿到需处理的原内容,上一个 Loader 处理后的结果会传给下一个接着处理,最后的 Loader 将处理后的最终结果返回给 Webpack。

plugins(插件)

常用的插件有

  • webpack-dev-server
  • copy-webpack-plugin
  • uglifyjs-webpack-plugin
  • webpack-spritesmith
  • clean-webpack-plugin
  • html-webpack-plugin
    ...还有好多好多

webpack-dev-server
非常常见,用于启动本地开发模式,本身是一个express服务器,封装了webpack-hot-middleware,实现了热更新。

devServer:{
  host:'0.0.0.0' || 'localhost',
  post:9000,//打开的端口
  open:true,//自动打开
  contentBase:path.join(_dirname,'src')//不设置的话,默认是当前执行的目录,一般是项目根目录,会在项目根目录查找index.html文件。
}

copy-webpack-plugin
在webpack相中拷贝文件或文件夹的方法。

new CopyWebpackPlugin({
  from:'.....',//需要拷贝的源目标文件
  to:'',//拷贝后存放的文件位置
})

uglifyjs-webpack-plugin
用来压缩优化js文件,webpack4+以上的版本可使用。
webpack4之前的版本是通过webpack.optimize.commonsChuckPlugin来压缩js

module.exports={
  optimization:{
    minimizer:true,//默认为true,效果就是压缩js代码
    splitChuncks:{
      chunks:'async',//'async':分割异步打包的代码,'all':同时分割同步和异步代码
      cacheGroups:{//默认的规则不会打包,需要单独定义
        vendors:{
          test:/[\\/]node_modules[\\/]/,
          name:'vendors'
        },
        commons:{
          test:/commons\.js/,
          name:'commons'
        }
      }
      
    }  
  }  
}

webpack-spritesmith
把零散的小图生成一张雪碧图,减少http请求

new SpritesmithPlugin({
      // 目标小图标
      src: {
        cwd: `src/assets/images/sprites`,
        glob: '*.png'
      },
      // 输出雪碧图文件及样式文件7
      target: {
        image: `dist/static/images/sprite-[hash].png`,
        css: [
          [
            `dist/static/css/sprite.css`, {
              formatOpts: {
                cssSelector: (groupName) => `.icon-${groupName.name}` // 修改生成的sprite css中类名定义
              }
            }
          ]
        ]
      },
      // 样式文件中调用雪碧图地址写法
      apiOptions: {
        cssImageRef: '../images/sprite-[hash].png'
      },
      spritesmithOptions: {
        algorithm: 'top-down'
      }
    })

clean-webpack-plugin
用来清除文件

// 删除文件 保留新文件
new CleanWebpackPlugin(['dist']),

html-webpack-plugin
为入口文件html加载js依赖,动态添加编译后的hash值文件,防止引用缓存文件的问题。

const HtmlWebpackPlugin = require('html-webpack-plugin')
  plugins: [
    new HtmlWebpackPlugin({ // 打包输出HTML
      minify: { // 压缩HTML文件
        removeComments: true, // 移除HTML中的注释
        collapseWhitespace: true, // 删除空白符与换行符
        minifyCSS: true// 压缩内联css
      },
      filename: 'a.html',
      template: 'a.html'
    }),
    new HtmlWebpackPlugin({ // 打包输出HTML
      minify: { // 压缩HTML文件
        removeComments: true, // 移除HTML中的注释
        collapseWhitespace: true, // 删除空白符与换行符
        minifyCSS: true// 压缩内联css
      },
      filename: 'b.html',
      template: 'b.html'
    }),
  ]

项目是多页的情况下,传入的html入口文件设置多个即可。
可以写一个提取html的函数,批量获取,组合成数组形式。

resolve配置

webpack在启动后会从配置的入口模块出发去找寻所有依赖的模块,resolve配置webpack如何找寻模块所对应的文件。
alias
resolve.alias配置项通过设置其他名字来将原路径映射成新的路径

resolve:{
  extensions: ['.js', '.json','.css'],//导入的语句中如果没带文件后缀名,webpack会自动带上后缀名去尝试文件是否存在,用于配置在尝试过程中用到的后缀列表。
  alias:{
    'api':utils.resolve('/src/common/api/'),//通过api关键字替换'/src/common/api/'
  }
}

总结

归结webpack在实际项目中做了哪些事情?
1、webpack从context设置的文件位置开始找寻
2、寻找entry里的所有文件名
3、在js文件编译过程中,遇到 import | require 引入的依赖文件,然后在依赖文件递归找寻所有依赖,最终打包在最终编译生成的文件。
4、webpack把所有生成的文件都输出到output.path路径中,以output.filename对应命名的模块来命名。

webpack之所以强大,是在于插件各式各样,总能满足你的需求。webpack4的新api大大的提高了Code Splitting 的体验,以上讲的内容还是浅显了点,具体的一些细节还是需要靠同志们自己愉快的撸起来,只有实操才是检验能力的唯一途径~


婊砸.png

最后,po上项目中的webpack相关依赖的版本情况

{
 "@babel/core": "^7.1.2",
    "@babel/plugin-proposal-class-properties": "^7.2.1",
    "@babel/plugin-transform-runtime": "^7.3.4",
    "@babel/preset-env": "^7.1.0",
    "@babel/preset-react": "^7.0.0",
    "@babel/runtime": "^7.3.4",
    "babel-loader": "^8.0.4",
    "babel-preset-env": "^1.7.0",
    "clean-webpack-plugin": "^2.0.0",
    "copy-webpack-plugin": "^5.0.3",
    "css-loader": "^1.0.0",
    "file-loader": "^2.0.0",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "image-webpack-loader": "^5.0.0",
    "jsx-loader": "^0.13.2",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^7.1.0",
    "script-loader": "^0.7.2",
    "style-loader": "^0.23.0",
    "uglifyjs-webpack-plugin": "^2.0.1",
    "url-loader": "^1.1.2",
    "webpack": "^4.20.2",
    "webpack-cli": "^3.1.2",
    "webpack-dev-server": "^3.1.9",
    "webpack-spritesmith": "^0.5.4",
    "clean-webpack-plugin": "^2.0.0",
    "copy-webpack-plugin": "^5.0.3",
}

相关文章

  • webpack入坑之路

    Hi ~ 许久没更新的小简书,自从换了新工作,日夜掉发式的疯狂加班,一个半月的时间学到了不少东西,趁热记录一波吧...

  • webpack学习(一)

    学习链接:webpack官方webpack中文网 webpack入坑之旅(一)不是开始的开始 webpack入坑之...

  • webpack入门

    webpack入坑之旅(一)不是开始的开始 Webpack傻瓜式指南(一)

  • 入坑Webpack

    起步 在开始学习Webpack之前,请先确保安装了Node.js,建议安装最新版的Node.js。然后就可以使用n...

  • webpack踩坑之路

    webpack+babel常用包和插件 没有设置repository和descriptionnpm WARN de...

  • ACCA入坑之路

    觉悟 对于一个财务专业的大三狗来说,这时候才认识到ACCA的重要性,莫不是太迟了? 还是好友一语道醒梦中人,我英语...

  • 写作入坑之路

    2019年,注定不平凡的一年。 一个偶然的机会知道了“个人品牌”这个概念,也果断加入课程学习。 这是学习个人品牌的...

  • 前端入坑之路

    作为一枚前端的小白,还是要给刚刚入坑的小朋友们总结几条建议以及总结前端学习之路。 相信刚刚开始准备学习前端之前,可...

  • 初入币圈

    话说自从订阅得到的李笑来<财富自由之路>,就开始入各种各样的坑,活在未来的坑、成长率的坑、长期的坑,还有007的坑...

  • Webpack掉坑之路(3)——webpack打包优化

    前文 本文旨在对webpack打包过程进行优化(生成的文件大小优化),以提高打开React网页时(一般是第一次)的...

网友评论

    本文标题:webpack入坑之路

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