likes
comments
collection
share

webpack入门笔记(一)

作者站长头像
站长
· 阅读数 19

webpack介绍

文件增加,逻辑增加,项目的复杂度提高,模块化需求出现 各个依赖文件的关系难以梳理,耦合程度较高,代码难以维护。 把所有依赖包都打包成为一个js文件(bundle.js)文件,会有效降低文件请求次数,一定程度提升性能。 逻辑多、文件多,项目复杂度提高

理解前端模块化

作用域 命名空间 模块化

运行时代码中变量,函数,对象的可访问性,可见性

  初始状态时,变量默认挂载在全局作用域:如var a = 1,即window.a = 1
  function test() {
    var b = 2
  }
  此时b处于局部作用域中
  window.b  // undefined
  ------
  在node环境中,全局作用域是global

使用函数作用域保护内部变量

// 使用自执行函数包裹代码,从外部无法访问
  var SusanModule = (function() {
    var name = 'Susan'
    var sex = '女孩'
    return function tell() {
      console.log(name)
      console.log(sex)
    }
  })()
  console.log(SusanModule.name) // undefined
  console.log(SusanModule.tell()) // Susan 女孩 
// ---------------------------------
// 传入window,把变量名写在模块内部
  // 标准模块化写法
  (function(window) {
    var name = 'Susan'
    var sex = '女孩'
    function tell() {
      console.log(name)
      console.log(sex)
    }
    window.SusanModule = { tell }
  })(window)

模块化的优点

  • 作用域封装
  • 可重用性
  • 解除耦合

模块化规范

### AMD Asynchronous Module Definition(异步模块定义)

/**
 * 模块名
 * 模块所需要的依赖
 * 模块内容
*/
define('getSum', ['math'], function(math) {
  return function(a, b) {
    console.log('sum:' + math.sum(a, b))
  }
})
// 模块的定义不会被绑定到全局对象上

### COMMONJS

// 通过require函数引入模块
const math = require('./math')
// 通过exports将模块导出
exports.getSum = function(a, b) {
  return a + b
}

### ES6 MODULE

// import 导入
import math from './math'
// export导出
export function sum(a, b) {
  return a + b
}

webpack打包机制

webpack与立即执行函数之间的关系

在执行打包后,被打包的模块会被作为参数传入webpack的方法里执行

 (function(modules) {
   var installedModules = {}
   // webpack加载的核心方法
   function __webpack_require__(moduleId) {
     /* code */
   }
   // ...
   return __webpack_require__(0) // entry file
 })([/* modules array */])

webpack打包的核心逻辑

function __webpack_require__(moduleId) {
  // 检测当前模块是否加载过,避免二次加载
  if(installedModules[moduleId]) {
    return installedModules[moduleId].exports
  }
  // 如果模块未曾加载过,那么为模块添加id,加入待加载的列队
  var module = installedModules[moduleId] = {
    i: moduleId,
    l: false,
    exports: {}
  }
  // 将该模块的this指向导出结果,并执行包装逻辑
  modules[moduleId].call(
    module.exports,
    module,
    module.exports,
    __webpack_require__
  )
  // 执行模块逻辑
  module.l = true
  return module.exports
}

webpack打包过程中都做了什么

  • 从入口文件开始,分析整个应用的依赖树
  • 将每个依赖模块包装起来,放到一个数组中等待调用
  • 实现模块加载的方法,并把他放到模块执行的环境中,确保模块间可以相互调用
  • 把执行入口文件的逻辑放在一个函数表达式,并立即执行这个函数

配置开发环境--NPM与包管理器

npm是一个包管理库,开发者可以上传分享自己的项目

理解包管理器

初始化一个项目

  npm init 

理解npm"仓库"与"依赖"的概念

初始化一个项目之后会生成package.json文件

{
  "name": "demo", // 包名称
  "version": "1.0.0", // 版本号
  "description": "",  // 描述信息
  "main": "index.js", // 文件主入口
  "scripts": {
    // 运行脚本内容
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "", // 作者
  "license": "ISC", // 许可证
  "dependencies": { // 依赖项
  // 当使用npm i xxx --save的时候,npm会将依赖项写在dependencies中 (npm5之后 -s是默认参数)
    "loadash": "^1.0.0"
  },
  // 执行npm i -s-d时生成,表示开发环境的依赖项
  // 构建工具一般放在devDependencies当中,如Eslint等
  "devDependencies": {}
}

理解npm"语义化版本"

  • "^version": 中版本和小版本

    在npm i的时候 会指定安装大版本号下最新的中版本号和小版本号
  • "~version": 小版本

    指定安装小版本
  • "version": 特定版本
  • 语义化版本的意义: 便于使包发布者把小版本推送到开发者手中

npm install 的过程

  • 寻找包版本信息文件(package.json)进行安装
  • 检查package.json的依赖,并检查项目中其他的版本信息文件
  • 如果发现呢新的包,就更新版本信息文件

    npm i 出错的时候检查更新版本信息文件是否出错

webpack核心特性

使用webpack构建简单工程

新建webpack.config.js文件,webpack在打包的时候会默认优先走webpack.config.js文件的配置

// webpack.config.js
module.exports = {
  // 入口文件
  entry: './app.js',
  // 文件的出口位置
  output: {
    // __dirname是nodejs中的全局变量,指向当前文件所在的路径
    path: path.join(__dirname, 'dist'),
    // 出口文件的文件名
    filename: 'app.bundle.js'
  },
    // dev开发环境服务器
  devServer: {
    port: 3000,  // 服务端口
    publicPath: '/dist'
  }
}

webpack中loader的配置应用

// app.js
import main from './main.js'
import './style/main.css'
// 以上引入了css..这在javascript里是无法解析的 但是使用了webpack后,只要有loader就可以解析js之外的文件类型

安装css-loader

npm install css-loader --save-dev

webpack中loader的配置应用

// webpack.config.js
module.exports = {
  entry: { /* ... */ },
  output: { /* ... */ },
  debServer: { /* ... */ },
  // webpack4配置loader
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',  // style-loader, 使得css文件可以生成一个style标签加载在页面里
          'css-loader' // css-loader,使得webpack可以加载css文件
          // 此处需要特别注意书写顺序,webpack加载loader的顺序是从右向左,要先加载css-loader之后才能生成style标签, 否则会报错
        ]
      }
    ]
  }
}

webpack中plugins的配置和应用

plugins和loaders的区别: loaders是文件夹加载器,使webpack可以认识这些文件 plugins主要用来监听编译过程中的一些事件,去改变编译结果 这里以压缩代码为举例 安装uglifyjs
npm install uglifyjs-webpack-plugin --save-dev
// webpack.config.js
// 引入uglifyjs
  const UglifyJSPlugin = require('uglify-webpack-plugin')
module.exports = {
  entry: { /* ... */ },
  output: { /* ... */ },
  debServer: { /* ... */ },
  // webpack4配置loader
  module: { /* ... */ },
  plugins: [
    new UglifyJSPlugin()
  ] // 压缩打包文件
}