webpack基础用法

Webpack

一、webpack是什么

官网:https://webpack.js.org

中文网:https://www.webpackjs.com

  • webpack是一种前端资源构建(打包)工具,一个静态模块打包器

  • 在webpack看来,前端所有资源文件(js/json/css/images/less/scss...)都会作为模块处理

  • webpack根据模块的依赖关系进行静态分析,打包生成对应的静态资源

  • webpack可以解决当前web开发中所面临的困境,它提供了:

    • 友好的模块化支持

    • 代码压缩混淆

    • 处理js兼容问题

    • 性能优化

隔行换色案例:没有使用webpack,浏览器不能兼容模块语法,会编译报错

1 先初始化一个空项目(npm init -y)目录结构:
2 |
3 |——dist  // dist文件用来存放打包后的文件
4 |——src
5 |   |——index.js
6 |   |——index.html
7 |——package.json

index.html中代码

 1 <body>
 2     <ul>
 3         <li>这是第1个li标签</li>
 4         <li>这是第2个li标签</li>
 5         <li>这是第3个li标签</li>
 6         <li>这是第4个li标签</li>
 7         <li>这是第5个li标签</li>
 8         <li>这是第6个li标签</li>
 9         <li>这是第7个li标签</li>
10     </ul>
11 </body>
12 
13 <script src="./index.js"></script>

index.js中代码

1 // 先需要安装jQuery,npm i -S jquery
2 import $ from "jquery";
3 
4 $(function () {
5     $("li:even").css("backgroundColor", "blue");
6     $("li:odd").css("backgroundColor", "pink");
7 });

二、webpack五个核心概念

这五个核心概念属于webpack的配置

1、entry

本项目应该使用哪个模块来作为构建其内部依赖图的开始(指定打包入口文件),打包入口文件默认为src/index.js

2、output

在哪里输出它所创建的 bundles,以及如何命名这些文件,打包输出文件默认值为dist/main.js

3、loader

loader让webpack能够去处理那些非js文件(webpack自身只理解js)

4、plugins

  • 插件可以用于执行范围更广的任务

  • 插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量

5、mode

通过选择development和production中的一个,来设置mode参数,可以启用相应模式下的webpack内置的变化

三、webpack安装

webpack是运行在node环境中的,需要Node>= 8.10和npm>=5.6的版本支持。

  • 在项目中安装webpack的方式如下:

    1 npm i -D webpack@4.44.2 webpack-cli@3.3.12
    2 # 由于目前这个2个工具大版本号已经升级,并且不兼容后续使用的工具,所以这边使用指定的低版本号
  • 安装好后可以通过先前提及过的npx命令来检查webpack的版本以确定是否安装成功:

    1 npx webpack --version
  • 在package.json文件中的scripts节点配置webpack运行脚本命令(指令名称自行决定):

  • 此时在终端运行npm run compact对之前隔行换色项目进行打包

    1 npm run compact
  • 打包完毕后会在当前项目目录下产生dist目录,里面会包含一个main.js文件,修改src/index.html文件,将原先的JavaScript文件引入修改为打包好的文件:

    1 <!-- <script src="./index.js"></script> -->
    2  <script src="../dist/main.js"></script>
  • 最终效果如下

四、webpack基本配置文件

1、单配置文件

在项目根目录下面创建一个webpack.config.js文件,webpack运行环境为nodejs,所以文件中的模块化规范为commonjs写法

该配置文件创建后会被webpack在打包时自动使用,因此文件名不能写错

 1 const path = require("path");
 2  3  module.exports = {
 4      // 打包模式  development |  production
 5      mode: "development",
 6      // 项目入口
 7      entry: "./src/index.js",
 8      // 项目出口
 9      output: {
10          path: path.resolve(__dirname, "dist"),
11          // [name]默认的名称为main(如果需要分目录,可以在名字前加文件夹名字)
12          filename: "[name].js",
13      },
14  };

2、多配置文件

  • 在项目根目录创建一个config目录,用于存放多配置文件

     

  • 这两个文件不像webpack.config.js一样会被webpack自动引用,因此需要在package.json中分别进行引入指定

  • 后续需要将项目打包成开发环境执行命令:

    npm run compact:dev
  • 如果需要将项目打包成生产环境执行命令:

    npm run compact:pro

五、webpack配置自动打包

  • 安装webpack-dev-server

    1 npm i -D webpack-dev-server@3.11.0
  • 修改package.json配置命令

  • 执行自定义打包命令

    1 npm run compact
    • 该命令执行后会处于实时监听状态

    • 会产生并运行一个临时服务器供我们预览,地址是:http://127.0.0.1:8080

    • 打包生成的输出文件会托管在项目根下(注意index.html中引入文件路径是否正确),但文件是虚拟的,无法看见,并不会产生dist目录,如果要得到打包的目录,还得运行之前的打包命令

  • 此外,webpack-dev-server自动打包操作还支持添加一些常见的配置选项

    • --open:打包完毕后自动运行浏览器

    • --host:配置打包服务器访问的地址

    • --port:配置打包服务器访问的端口

    1 "scripts": {
    2     "compact": "webpack-dev-server --open --host 127.0.0.1 --port 8888"
    3 }

六、webpack配置默认预览页

在上节中需要在http://127.0.0.1:8080点击src文件才能预览页面效果,比较麻烦,可以通过配置进一步简化

  • 安装一个扩展模块

    1 npm i -D html-webpack-plugin
  • 然后修改webpack的配置文件(注意使用的是单配置文件还是多配置文件,到对应的文件中修改),增加以下配置
     1 const HtmlWebpackPlugin = require("html-webpack-plugin");
     2 
     3 module.exports = {
     4     // ....
     5     plugins: [
     6         new HtmlWebpackPlugin({
     7             template: "./src/index.html",
     8             title: "jQuery的隔行变色"
     9         }),
    10     ],
    11 }

    上面代码的title配置项的作用是替换index.html中head标签里默认显示的标题,这个值可以在模板中通过特定的标记输出:

    1 <title><%= htmlWebpackPlugin.options.title %></title>
  • 注:修改配置文件后需要重新启动打包服务;使用该插件后,除了我们手动引入的main.js,还会自动在视图中引入打包好的main.js

七、webpack加载器

在实际开发中,webpack只能打包处理以.js为后缀的模块,其他后缀的模块webpack处理不了,需要使用loader加载器才能正常打包

1、处理css文件

没有安装css加载器的时候打包包含css文件的项目会报错

  • 安装css加载器:

    1 npm i -D style-loader css-loader
  • 安装好加载器后需要在配置文件webpack.config.js(例:单文件)中进行配置

    1 module: {
    2     rules: [
    3         {test: /\.css$/, use: ["style-loader", "css-loader"]}
    4     ]
    5 }
  • 在写加载器use的时候,需要注意

    • use数组中指定的加载器顺序是固定

    • 多个加载器调用的顺序是:从后往前、从下往上(倒序)

2、处理less文件

  • 安装less加载器:

    1 npm i -D less-loader less
  • 安装好加载器后需要在配置文件webpack.config.js(例:单文件)中进行配置

    1 module: {
    2     rules: [
    3         {test: /\.less$/, use: ["style-loader", "css-loader", "less-loader"]}
    4     ]
    5 }

3、处理scss文件

  • 安装scss加载器

    1 npm i -D sass-loader node-sass
  • 安装好加载器后需要在配置文件webpack.config.js(例:单文件)中进行配置

    1 module: {
    2     rules: [
    3         {test: /\.scss$/, use: ["style-loader", "css-loader", "sass-loader"]}
    4     ]
    5 }

4、自动添加css兼容前缀

部分样式需要添加特定浏览器前缀才会被浏览器支持

  • 安装对应加载器

    1 npm i -D postcss-loader autoprefixer
  • 随后在项目根目录下创建postcss配置文件postcss.config.js

    1 const autoprefixer = require("autoprefixer")
    2 
    3 module.exports = {
    4     plugins: [autoprefixer]
    5 }
  • webpack.config.js文件中加入针对前缀兼容的打包规则:

    1 module: {
    2     rules: [
    3         {test: /\.css$/, use: ["style-loader", "css-loader", "postcss-loader"]}
    4     ]
    5 }

IE浏览器下,打包产生的代码可能无法运行看到效果,如果出现SCRIPT5009: “Promise”未定义的报错,要先安装babel-polyfill

1 npm i -D babel-polyfill

之后修改webpack的打包入口配置:

1 entry: ["babel-polyfill", "./src/index.js"]

5、处理图片和字体

  • 安装

    1 npm i -D url-loader file-loader
  • 安装好加载器后需要在配置文件webpack.config.js(例:单文件)中进行配置

    1 module: {
    2     rules: [
    3         {
    4             test: /\.jpg|png|gif|bmp|ttf|eot|svg|woff|woff2$/,
    5             use: "url-loader?limit=16940"
    6         }
    7     ]
    8 }

    注意:?之后是loader的参数项,limit参数用于指定图片的大小,单位为字节,小于limit指定的大小,会被转化成base64编码形式

    如果图片被转化成base64编码的形式,通过打包得到的dist目录中就没有对应的图片文件,如果没有被转化成base64编码的形式,打包得到的文件中会有对应的文件

6、处理js文件中的高级语法

像工厂模式、构造函数这些属于js高级原发,使用babel完成js兼容处理

  • 安装babel转换器相关包:

    1 npm i -D babel-loader @babel/core @babel/runtime
  • 再去安装babel语法插件相关的包:

    1 npm i -D @babel/preset-env @babel/plugin-transform-runtime @babel/plugin-proposal-class-properties
  • 再去根目录下创建babel配置文件babel.config.js并初始化:

    1 module.exports = {
    2     presets: ["@babel/preset-env"],
    3     plugins: ["@babel/plugin-transform-runtime","@babel/plugin-proposal-class-properties"]
    4 }
  • 最后在webpack的配置文件中设置打包规则:

    1 module: {
    2     rules: [
    3         {
    4             test: /\.js$/,
    5             use: "babel-loader",
    6             exclude: /node_modules/
    7         }
    8     ]
    9 }

八、webpack其他细节

为了观察打包的细节,使用非自动打包

1、entry多入口

前面使用webpack打包的方式是针对SPA形式的页面,如果项目中有多个页面就不适用了,此时需要将webpack的入口配置成多入口形式

例如:需要将index.htmllogin.html两个页面同时进行打包,entry改成如下形式

1 entry: {
2     main: "./src/index.js",
3     login: "./src/login.js",
4     // ....
5 }

多文件/多入口打包的方式可能出现的问题:一个大型项目,js等文件会以功能模块进行分目录存储,但是即使多入口路径不存在冲突,由于output输出是统一的,那么就可能出现文件同名而导致文件覆盖的情况

因此,如果是多入口文件的打包,对于输出文件的输出要做一些处理:

1 output: {
2     // join或resolve均可
3     path: path.join(__dirname, "dist"),
4     // `:N`中的N为数字,取值范围为1-20,加上表示指定Hash的长度(可选),不加默认为20位hash值
5     filename: "[name]-[contentHash:N].js",
6 },

2、路径别名与默认后缀

Vue中可以使用@符号表示src目录,使用起来比较轻松,但是再webpack中使用会报错,需要进行配置

配置方法:修改webpack配置文件,在配置选项中添加resolve选项,增加配置别名

1 resolve: {
2     // 配置解析模块路径别名:优点简写路径,缺点路径没有提示
3     alias: {
4         // 定义一个@,可在import引入时使用
5         "@": path.join(__dirname, "src"),
6     },
7     // 设置可以忽略不写的后缀
8     extensions: [".js", ".json", ".vue"],
9 }

3、忽略打包

webpaack中的externals选项提供了不从bundle捆绑中使用依赖的方式。

在开发项目时,有些外部模块通过CDN链接使用script标签引入到页面中可能要比通过打包使用更加方便,例如jQuery库。此时就可以使用externals忽略打包的方式去指定哪些库不需要webpack进行打包。

例如,需要忽略对jQuery的打包,则可以写成:

1 externals: {
2     jquery: 'jQuery',
3     // .....
4 }

注意:不被webpack打包的外部依赖,后期依旧可以通过以下方式使用

  • script标签引入(推荐)

  • import导入

    • import ... from "xxx"

    • import { a, b, c } from "xxx"

4、打包处理vue文件

  • 在项目中安装vue

    1 npm i -S vue
  • 创建vue文件:/src/vue/demo.vue

     1 <template>
     2     <div>
     3         {{ msg }}
     4     </div>
     5 </template>
     6 
     7 <script>
     8 export default {
     9     data() {
    10         return {
    11             msg: "Hello World",
    12         };
    13     },
    14 };
    15 </script>
  • 创建vue入口文件:/src/vue/app.js

    1 import Vue from "vue";
    2 import App from "@/vue/demo.vue";
    3 
    4 new Vue({
    5     el: '#app',
    6     render: h => h(App)
    7 })
  • 在打包入口指定vue文件入口

    1 entry: {
    2     demo: "./src/vue/app.js",
    3     // .....
    4 },
  • 进行打包会出错,安装loader

    1 npm i -D vue-loader vue-template-compiler
  • webpack.config.js中配置

     1 const VueLoaderPlugin = require("vue-loader/lib/plugin");
     2 
     3 module.exports = {
     4     plugins: [
     5         new VueLoaderPlugin(),
     6     ],
     7     module: {
     8         rules: [
     9             {
    10                 test: /\.vue$/,
    11                 loader: "vue-loader",
    12             },
    13         ]
    14     }
    15 }

九、配置文件

1、postcss.config.js

自动添加css兼容前缀(参考第七节第4小节)

1 const autoprefixer = require("autoprefixer")
2 
3 module.exports = {
4     plugins: [autoprefixer]
5 }

2、babel.config.js

处理js文件中的高级语法(参考第七节第6小节)

1 module.exports = {
2     presets: ["@babel/preset-env"],
3     plugins: ["@babel/plugin-transform-runtime","@babel/plugin-proposal-class-properties"]
4 }

3、webpack.config.js

 1 // 默认单文件配置
 2 const path = require('path');
 3 // 配置默认预览页
 4 const htmlWebpackPlugin = require('html-webpack-plugin');
 5 // 引入vue打包插件
 6 const VueLoaderPlugin = require('vue-loader/lib/plugin');
 7 
 8 module.exports = {
 9     // 使用的打包模式:development | production
10     mode: "development",
11 
12     // 打包入口
13     entry: {
14         main: ["babel-polyfill", "./src/index.js"],
15         login: "./src/login.js",
16         demo: "./src/vue/app.js"
17     },
18         
19     // 输出文件位置
20     output: {
21         path: path.join(__dirname, 'dist'),
22         filename: '[name]-[contentHash:10].js'
23     },
24     plugins: [
25         new htmlWebpackPlugin({
26             // 指定默认视图位置
27             template: './src/index.html',
28             title: 'jquery的隔行换色'
29         }),
30         new VueLoaderPlugin(),
31     ],
32     module: {
33         rules: [
34             { test: /\.css$/, use: ["style-loader", "css-loader", "postcss-loader"] },
35             { test: /\.less$/, use: ["style-loader", "css-loader", "less-loader"] },
36             { test: /\.scss$/, use: ["style-loader", "css-loader", "sass-loader"] },
37             {
38                 test: /\.jpg|png|gif|bmp|ttf|eot|svg|woff|woff2$/,
39                 use: "url-loader?limit=16940"
40             },
41             {
42                 test: /\.js$/,
43                 use: "babel-loader",
44                 exclude: /node_modules/
45             },
46             {
47                 test: /\.vue$/,
48                 use: "vue-loader",
49             },
50         ],
51     },
52     resolve: {
53         // 起路径别名
54         alias: {
55             "@": path.join(__dirname, "src"),
56             "$css": path.join(__dirname,"src/css")
57         },
58         // 默认后缀可以省略
59         extensions: [".js", ".json", ".vue"],
60     },
61     // 忽略打包配置
62     externals: {
63         // jquery: 'jQuery',
64     }
65 }

 

 

posted @ 2021-05-17 00:35  大米饭盖饭  阅读(260)  评论(0)    收藏  举报