webpack

Posted sheun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了webpack相关的知识,希望对你有一定的参考价值。

一,介绍
1. webpack是js 应用程序的静态模块打包器
2. loader语法转化 less/sass/stylus转成css, es6转es5,插件的使用     loader的作用 https://segmentfault.com/a/1190000014408973
3. html/css/js代码压缩合并(打包)
4. webpack可以在开发期=期间提供一个开发环境  自动打开浏览器  保存时自动刷新
5. 项目一般先打包在上线

二,webpack 安装使用
1. 首先全局安装webpack : npm install webpack -g
2. 初始化项目 : cd 到 项目目录,执行npm init -y
会生成package.json文件
3. 项目中安装依赖包(webpack4.0以上,文件名称不能与那么重复,否则会报错)npm install --save-dev webpack和 npm install --save-dev webpack-cli 两个依赖包会生成node_moudles

4. 修改package.json 添加属性,scripts
5. 新建webpack.config.js文件 官方文档(https://www.webpackjs.com/concepts/) 

默认入口是src/index.js

因为打包的入口文件是main.js,如果要打包多个文件时应该导入对应的文件 

 

 

 6. 使用html-webpack-plugin依赖包,自动生成html文件,(因为打包后的dist/bundle.js,在index.html中引入是有缺陷的,不需要手动引入)https://www.webpackjs.com/concepts/#插件-plugins- 打包后生成一个index.html文件 

7.处理css https://www.webpackjs.com/concepts/#loader loader 让 webpack 能够去处理那些非 javascript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。 

 

 

 

8. 上面 虽然处理了css,但是如果有多个css文件,打包后index.html中会引入多个css文件,而且打包后的css是在bundle.js中,为了让css打包成一个css文件,让页面引入 npm install --save-dev mini-css-extract-plugin

css打包成一个css文件

 

 

 9.处理less npm install less less-loader --save-dev 

 

 10. 处理图片 npm install --save-dev url-loader file-loader

 

 11.打包后的图片默认生成在dist目录,要配置打宝图片生成的目录 

 

 12. webpack每次打包默认把之前dist目录的文件全部清空 的插件 装包,导入插件,使用插件 

 

 三,webpack开发服务器

(在内存中生成)(也就是开发环境,和生产环境不同,dev的时候自动刷新,保存代码自动刷新代码)

 

 

 

四,生产环境 和 开发环境

生产环境和开发环境刚好相反,开发环境在本地运行,而生产环境是要产出运行在线上服务器面向用户使用的代码,因此两者的构建目标差异很大,比如打包后的文件在生产环境中要尽可能的小,逻辑代码分离,优化静态资源(压缩图片)等。

因此开发环境和生产环境不能共用一份webpack配置文件,需要分别指定

但是两个环境还是有很多配置可以共用的,比如entry、output、module等,因此可以把公共部分的配置抽离出来放到一个独立的文件然后进行合并,我们可以使用webpack-merge工具来进行合并。

注意:entry、output、module这些配置在我们当前示例通用,但未必适合所有项目。

 

 

npm i webpack-merge

 

开始拆分webpack.config.js文件,拆分后这个文件就不要了。

新建config文件夹:

配置文件

1.0 config/webpack.base.js(绝对路径的地址需要改一下)

 

 

 

// 存放公共的部分
const path = require(\'path\')

// 引入自动生成 html 的插件
const HtmlWebpackPlugin = require(\'html-webpack-plugin\')

// 引入分离 css 文件的 模块
const MiniCssExtractPlugin = require(\'mini-css-extract-plugin\')

// 导入清除插件, 可以在每次打包之前, 清除 dist目录的内容
const { CleanWebpackPlugin } = require(\'clean-webpack-plugin\')


// 配置webpack的配置文件, 需要将配置的对象导出, 给webpack使用
module.exports = {
  // 入口 entry, 从哪个文件开始打包
  entry: \'./src/main.js\',

  // 出口 output, 打包到哪里去
  output: {
    // 打包输出的目录 (输出的目录必须是一个绝对路径)
    path: path.join(__dirname, \'../dist\'),
    // 打包后生成的文件名
    filename: \'js/bundle.js\'
  },

  // 配置module模块加载规则
  // 默认, webpack只认识json, javascript, 不认识其他文件, 如果希望打包处理其他文件, 需要配置对应loader
  module: {
    rules: [
      // (1) 配置css文件的解析
      {
        // 正则: 匹配所有以css结尾的文件
        test: /\\.css$/,
        // 实际处理顺序: 从右往左
        // css-loader 让webpack能够识别解析 css 文件
        // style-loader 通过动态的创建style标签的方式(js), 让解析后的css内容, 能够作用到页面中
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: \'../\',
            },
          }, 
          \'css-loader\'
        ]
      },
      // (2) 配置less文件的解析
      {
        test: /\\.less$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: \'../\',
            },
          }, 
          \'css-loader\', 
          \'less-loader\'
        ]
      },
      // (3) 配置图片文件的解析  i 表示忽视大小写  .PNG
      {
        test: /\\.(png|jpg|gif)$/i,
        use: [
          // url-loader 如果不配置, 默认都会将文件转成base64字符串的格式
          {
            loader: \'url-loader\',
            // 8k以内, 转成base64, 节约请求次数, 8k以外, 单独一个文件请求
            options: {
              limit: 8 * 1024,
              // 配置输出的文件名
              name: \'[name].[ext]\',
              // 配置静态资源的引用路径
              publicPath: "../images/",
              // 配置输出的文件目录
              outputPath: "images/"
            }
          }
        ]
      },
      // (4) 配置新版本js文件的解析
      {
        test: /\\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: \'babel-loader\',
          options: {
            presets: [\'@babel/preset-env\']
          }
        }
      }
    ]
  },

  // 配置插件
  plugins: [
    // 自动生成 html 的插件
    new HtmlWebpackPlugin({ template: \'./public/index.html\' }),

    // 分离css的插件, 定义打包好的文件的e存放路径和文件名
    new MiniCssExtractPlugin({ 
      filename:\'css/index.css\'
    }),

    // 清除dist目录的插件
    new CleanWebpackPlugin()
  ]
}

2. webpack.dev.js

// 存放开发模式下的配置 development
const base = require(\'./webpack.base.js\')
// 用于合并webpack配置的插件
const merge = require(\'webpack-merge\')

// merge 可以接受多个参数, 把参数对象合并成一个对象
// 后面的对象属性, 会覆盖前面的对象属性
module.exports = merge(base, {
  // 配置开发服务器
  devServer: {
    port: 3000, // 端口号
    open: true // 自动打开浏览器
  },
  mode: \'development\'  //当前是开发环境
})

3. webpack.pro.js

// 存放生产模式的配置 production
const base = require(\'./webpack.base.js\')
// 用于合并webpack配置的插件
const merge = require(\'webpack-merge\')

// merge 可以接受多个参数, 把参数对象合并成一个对象
// 后面的对象属性, 会覆盖前面的对象属性
module.exports = merge(base, {
  mode: \'production\' // 声明当前是生产环境
})

4. 修改scripts启动命令,注意指定配置文件的路径变化

package.json

{
  "scripts": {
    "build": "webpack --config config/webpack.pro.js",
    "dev": "webpack-dev-server --config config/webpack.dev.js"
  },
}

五,多入口多出口

 

 

六, 提取公共模块

在 index 和 about 这两个独立入口文件中, 如果引入了相同的模块, 这些模块会被重复打包, 我们需要提取公共模块!

将 jquery 库分别引入到 index.js 和 about.js 中。

查看打包后的 about.bundle.jsindex.bundle.js 文件源码,会发现它们都把 jquery.js 打包进去了,这样做的后果不敢想象。所以我们需要把类似公共的依赖模块提取到一个单独的文件中。

 

 config/webpack.base.js

module.exports = {
    // 其他代码
    // + 提取公共模块配置
    optimization: {
        splitChunks: {
            chunks: \'all\'    // 提取所有文件的共同模块
        }
    }
}

七, webpack处理vue

 

vue单文件组件

 

 

 

vue-loader的配置(和配置less和css一样)

Vue Loader 是一个 webpack 的 loader,它允许你以一种名为单文件组件的格式撰写 Vue 组件:

npm i vue-loader vue-template-compiler
// webpack.config.js
const VueLoaderPlugin = require(\'vue-loader/lib/plugin\')

module.exports = {
  module: {
    rules: [
      // ... 其它规则
      {
        test: /\\.vue$/,
        loader: \'vue-loader\'
      }
    ]
  },
  plugins: [
    // 请确保引入这个插件!
    new VueLoaderPlugin()
  ]
}

 

webpack项目中路由的配置

  • 新建views文件夹,存放Home.vue组件和Login.vue组件

  • 安装vue-router

// 配置所有的路由的功能
// 模块化环境开发
import Vue from \'vue\'
import VueRouter from \'vue-router\'
import Login from \'../components/Login.vue\'
import Home from \'../components/Home.vue\'
Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    { path: \'/login\', component: Login },
    { path: \'/home\', component: Home}
  ]
})

export default router

vue-cli 脚手架环境

通过学习webpack的配置, 我们更深入的理解了脚手架里面的一些配置原理,

下面会介绍一下, 脚手架中移动端的rem配置 和 反向代理配置, 这些都是实际工作中常用的

先通过脚手架创建项目

vue create vue-mobile

在项目根目录新建 vue.config.js进行配置, 这个vue.config.js 会覆盖默认cli的webpack配置, 非常方便

module.exports = {
  devServer: {
    port: 3000,
    open: true
  }
}

 

移动端 rem 布局 - 插件 postcss-pxtorem的配置       https://www.cnblogs.com/lml2017/p/9953429.html

npm i lib-flexible postcss-px2rem

在 public 中的 index.html 中删除 meta 标签

flexible会为页面根据屏幕自动添加<meta name=\'viewport\' >标签,动态控制initial-scale,maximum-scale,minimum-scale等属性的值。

在 src / main.js 中导入插件包

// 导入 rem 的 js, 动态的设置了, 不同屏幕的html根元素的 font-size
import \'lib-flexible\'

配置 vue.config.js

module.exports = {
  devServer: {
    port: 3000,
    open: true
  },
  // rem 的配置
  css: {
    loaderOptions: {
      css: {},
      postcss: {
        plugins: [
          require(\'postcss-px2rem\')({
            // 适配 375 屏幕, 设计图750中量出来的尺寸要 / 2
            // 配置成 37.5 是为了兼容 没有适配 rem 布局的第三方 ui 库
            remUnit: 37.5
          })
        ]
      }
    }
  }
}

 

 

反向代理的配置说明

服务端与服务端没有跨域,将本地的请求代理到服务器上

webpack的反向代理, 可以起一个临时的代理服务器, 帮助解决在开发过程中的跨域问题, 就算跨域了也能拿到后台的数据

安装 axios, 发送ajax请求

客户端分送这种请求会跨域

https://c.y.qq.com/mv/fcgi-bin/getmv_by_tag?g_tk_new_20200303=5381&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=GB2312&notice=0&platform=yqq.json&needNewCode=0&cmd=shoubo&lan=all
import axios from \'axios\'
export default {
  async created () {
    const url = `/music/getmv_by_tag?g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=GB2312&notice=0&platform=yqq.json&needNewCode=0&cmd=shoubo&lan=all`
    
    const res = await axios.get(url)
    console.log(res)
  }
}

配置代理 (配置vue.config.js文件)

module.exports = {
  devServer: {
    port: 3000,
    open: true,
    proxy: {
      \'/music\': {
        target: \'https://c.y.qq.com/mv/fcgi-bin/\',    //当前电脑请求代理到的地址(也就是后端地址)
        pathRewrite: { \'^/music\': \'\' }              //请求的路径要加上/music,但是真正发的请求路径有不包括/music,只是为了匹配到这个服务端的地址
      }
    }
  },
  // rem 的配置
  // ....
}

 

以上是关于webpack的主要内容,如果未能解决你的问题,请参考以下文章

Vue报错:Uncaught TypeError: Cannot assign to read only property 'exports' of object 的解决方法(代码片段

如何使用webpack加载库源映射?

浅析 -- webpack

报错:✘ http://eslint.org/docs/rules/indent Expected indentation of 0 s paces but found 2(代码片段

报错:✘ http://eslint.org/docs/rules/indent Expected indentation of 0 s paces but found 2(代码片段

无法创建中继容器; graphql.js 文件似乎有 webpack 工件?