webpack基本用法

网页中常见的静态资源:

JS:.js   .jsx   .coffee   .ts(TypeScript  类c#语言)

CSS:.css  .less   .sass  .scss

Images:.jpg  .jpeg  .png   .gif  .bmp

字体文件(Fonts): .svg  .ttf   .eot   .woff   .woff2

模板文件: .ejs   .jade   .vue

网页中会引用很多静态资源,当静态资源多了以后,因为要发起很多的二次请求,就会导致网页加载速度慢,同时还要处理各种错综复杂的依赖关系,webpack可以帮助解决这些问题

webpack是前端的一个项目构建工具,是基于node.js开发出来的一个前端工具。

借助于webpack这个前端自动化构建工具,可以完美的实现资源的合并、打包、压缩、混淆等诸多功能

webpack安装的两种方式

1、运行 npm i webpack -g 全局安装webpack,这样可以全局使用 webpack命令

安装完webpack     需要安装一个webpack-cli 
npm install webpack-cli -g 

因为在webpack 3中,webpack本身和它的CLI以前都是在同一个包中,但在第4版中,他们已经将两者分开来更好地管理它们。

2、在项目根目录中,运行 npm i webpack --save-dev 安装到项目依赖中,本地也需要安装webpack-cli

webpack-最基本的使用方式

1、建一个文件夹(webpack-study)来存放我们的项目。(已全局安装webpack)

2、webpack-study文件夹 下创建dist文件夹和src文件夹。

3、src文件夹 下创建css、js、images文件夹,index.html(项目入口文件)、 main.js(项目js入口文件)

4、依赖jQuery实现列表隔行变色功能,需要安装一下jQuery,打开终端,运行以下命令:

npm init -y

npm i jquery -s   

运行完以后会在webpack-study文件夹下,有一个node_modules文件夹,里面装了jquery包。

且在webpack-study文件夹下,多了一个package-lock.json文件

5、导入jQuery

注意:以前我们都是直接在index.html文件中直接用script标签引入要用的js文件,但是在应用webpack的时候,不推荐在index.html中直接引入任何包和css文件。

而是在main.js文件中利用import导入要用的任何包和CSS文件,然后在index.js中只引入main.js就行。

main.js

// main.js 是项目的JS入口文件
// 导入jquery
// import *** from *** 是ES6中导入模块的方式
// 由于ES6代码太高级,浏览器解析不了,所以执行这一行的时候会报错
import $ from 'jquery'
// 相当于node.js中的  const $ = require('jquery')

$(function () {
    // odd奇数 但li标签索引从0开始
    $('li:odd').css('backgroundColor', '#F0F');
    // even偶数
    $('li:even').css('backgroundColor', function () {
        return '#0FF';
    })
})

index.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <!-- 不推荐在这里引用任何包和css文件 -->
    <!-- 由于ES6代码太高级,main.js中有ES6语句,浏览器解析不了,所以执行这一行的时候会报错 -->
    <!-- <script src="main.js"></script> -->
    <!-- 通过webpack这么一个前端构建工具,把main.js做一下处理,生成一个bundle.js文件 -->
    <script src="../dist/bundle.js"></script>
</head>
<body>
    <!-- ul>li*10{这是第$个li}  然后tab键,一下出现下面列表 -->
    <ul>
        <li>这是第1个li</li>
        <li>这是第2个li</li>
        <li>这是第3个li</li>
        <li>这是第4个li</li>
        <li>这是第5个li</li>
        <li>这是第6个li</li>
        <li>这是第7个li</li>
        <li>这是第8个li</li>
        <li>这是第9个li</li>
        <li>这是第10个li</li>
    </ul>
</body>
</html>

此时还没有bundle.js文件

6、webpack-最基本的配置文件的使用:在webpack-study文件夹下,创建一个webpack.config.js文件

(1)webpack能够处理JS文件的相互依赖关系

(2)webpack能够处理JS的兼容问题,把高级的、浏览器不识别的语法,转为低级的,浏览器能正常识别的语法

(3)这个配置文件,其实就是一个JS文件,通过node中的模块操作,向外暴露了一个配置对象

(4)在配置文件中需要指定 入口 和 出口

// webpack.config.js
const path = require('path')
module.exports = {
    // 入口:表示要使用webpack打包哪个文件
    entry: path.join(__dirname, './src/main.js'),
    // 出口:输出文件的相关配置
    output: {
        // 指定打包好的文件,输出到哪个目录中去
        path: path.join(__dirname, './dist'),
        // 指定输出的文件名称
        filename: 'bundle.js'
    }
}

在终端运行webpack命令,这样在dist文件下就生成了一个bundle.js文件

此时用浏览器打开index.js文件就可以看见页面渲染效果了。

但是有一个问题是:我们每改变一次main.js文件,就要重新运行一次webpack命令

7、webpack-dev-server的基本使用

运行npm i webpack-dev-server -D 把这个工具安装到项目的本地开发依赖

这个工具要想正常运行,需要先在本地安装webpack和webpack-cli

将webpack-dev-server命令配置到package.json文件中:配置dev这个命令,这样就可以在终端直接npm run dev 就可以运行webpack-dev-server了

"scripts": {

"test": "echo \"Error: no test specified\" && exit 1",

"dev": "webpack-dev-server"    //在package.json文件中配置这一行命令

},

红框中说明项目本地运行地址,在浏览器中输入 http://localhost:8080/  就可以打开项目

绿框中说明webpack打包输出的文件在该项目根路径下,下面绿字说明打包生成的文件为bundle.js

所以:在index.html中要将<script src="../dist/bundle.js"></script>换成<script src="/bundle.js"></script>

这个bundle.js文件是托管在项目的根路径下,所以我们看不见这个文件,但是这个文件存在,可以在浏览器中输入地址http://localhost:8080/bundle.js打开文件。

运行完npm run dev以后,我们改动main.js文件中的内容,保存以后,项目就会自动运行,重新打包生成新的bundle.js文件替换原来的

但是,运行npm run dev以后,需要我们手动点击http://localhost:8080/  才可以打开项目。

8、webpack-dev-server的常用命令参数

在package.json文件中配置:

"dev": "webpack-dev-server --open"    运行npm run dev 会自动打开浏览器

"dev": "webpack-dev-server --open --port 3000"   运行npm run dev 会自动打开浏览器,此时的端口号为3000

"dev": "webpack-dev-server --open --port 3000 --contentBase src" --contentBase src指定运行的根路径,这样打开http://localhost:3000/就直接是我们的项目主页面了,因为src文件夹下有index.html

"dev": "webpack-dev-server --open --contentBase src --hot"  --hot  添加这个命令以后,更新main.js中的代码,自动运行不会重新生成bundle.js文件替换之前的bundle.js文件,而是以补丁的形式更新

9、webpack-dev-server配置命令的第2种方式(了解即可)

package.json中:

"dev": "webpack-dev-server"

在webpack.config.js中配置

10、html-webpack-plugin插件的两个基本作用

index.html是物理磁盘上的HTML页面,但bundle.js是托管到内存中的文件,那么,如何把HTML页面也导入到内存中呢?

(1)安装插件 npm i html-webpack-plugin -D

(2)在webpack.config.js中配置

// webpack.config.js
const path = require('path')

// 导入在内存中生成HTML页面的插件
// 只要是插件,都一定要放到plugins节点中去
const htmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    // 入口:表示要使用webpack打包哪个文件
    entry: path.join(__dirname, './src/main.js'),
    // 出口:输出文件的相关配置
    output: {
        // 指定打包好的文件,输出到哪个目录中去
        path: path.join(__dirname, './dist'),
        // 指定输出的文件名称
        filename: 'bundle.js'
    },
    // 配置插件的节点,是一个数组
    plugins: [
        // 创建一个在内存中生成HTML页面的插件
        new htmlWebpackPlugin({
            // 指定模板页面,将来会根据指定的模板路径,去生成内存中的页面
            template: path.join(__dirname, './src/index.html'),
            // 指定生成的页面的名称
            filename: 'index.html'
        })
    ]
}

当使用了这个插件以后,我们就不需要手动处理bundle.js的引用路径了,因为这个插件,已经自动帮我们创建了一个合适的script,并引用了正确的bundle.js的路径。因此就可以把物理磁盘中的index.html中<script src="/bundle.js"></script>注释掉了。

运行npm run dev,打开页面以后,可以查看页面源代码,我们就会发现:

内存中的index.html比我们磁盘中的index.html,在body底部多了一行<script type="text/javascript" src="bundle.js"></script>

下面为内存中的index.html


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <!-- 不推荐在这里引用任何包和css文件 -->
    <!-- 由于ES6代码太高级,main.js中有ES6语句,浏览器解析不了,所以执行这一行的时候会报错 -->
    <!-- <script src="main.js"></script> -->
    <!-- 通过webpack这么一个前端构建工具,把main.js做一下处理,生成一个bundle.js文件 -->
    <!-- <script src="../dist/bundle.js"></script> -->
    <!-- <script src="/bundle.js"></script> -->
</head>
<body>
    <!-- ul>li*10{这是第$个li}  然后tab键,一下出现下面列表 -->
    <ul>
        <li>这是第1个li</li>
        <li>这是第2个li</li>
        <li>这是第3个li</li>
        <li>这是第4个li</li>
        <li>这是第5个li</li>
        <li>这是第6个li</li>
        <li>这是第7个li</li>
        <li>这是第8个li</li>
        <li>这是第9个li</li>
        <li>这是第10个li</li>
    </ul>
<script type="text/javascript" src="bundle.js"></script></body>
</html>

html-webpack-plugin插件的两个基本作用是:

(1)自动在内存中根据指定页面生成一个内存中的页面

(2)自动把打包好的bundle.js追加到页面中去

11、loader-配置处理css样式表的第三方loader

在css文件夹下,建一个index.css文件,以前我们是在index.html中直接用link引入CSS文件,但是这样会发起二次请求,所以不建议这样做。

在mian.js中,使用import导入index.css

// 使用import语法,导入CSS样式表
import './css/index.css'

注意:webpack,默认只能打包处理JS类型的文件,无法处理其他的非JS类型的文件;

如果要处理非JS类型的文件,需要手动安装一些合适的第三方loader加载器;

(1)如果想要打包处理 CSS 文件,需要安装 npm i style-loader css-loader -D

(2)打开 webpack.config.js 这个配置文件,在里面新增一个配置节点,叫做module,是一个对象;在这个module对象身上,有个rules属性,是个数组,在这个数组中,存放了所有第三方文件的匹配和处理规则

在webpack.config.js文件的exports中增加module:

    // 这个节点,用于配置 所有第三方模块加载器
    module: {
        // 所有第三方模块的 匹配规则
        rules: [
            // 配置处理.css文件的第三方loader规则
            { test: /\.css$/, use: ['style-loader', 'css-loader']}
        ]
    }

12、loader-分析webpack调用第三方loader的过程

例如,在处理CSS文件,找到对应规则后,会先调用'css-loader',然后把处理结果给'style-loader',调用'style-loader'处理完以后,直接交给webpack进行打包合并,输出到bundle.js中去。

13、loader-配置处理less文件的loader

(1)在css文件夹下建一个文件index.less,写一些样式,然后,在mian.js中,使用import导入index.less

// 使用import语法,导入less样式表
import './css/index.less'

(2)装包

npm i less-loader -D

npm i less -D

(3)配置规则

            // 配置处理.less文件的第三方loader规则
            { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']},

14、loader-配置处理scss文件的loader

(1)在css文件夹下建一个文件index.scss,写一些样式,然后,在mian.js中,使用import导入index.scss

// 使用import语法,导入SCSS样式表
import './css/index.scss'

(2)装包

npm i sass-loader -D

cnpm i node-sass -D   (一般这一步用npm会装不成功,用cnpm比较好)

(3)配置规则

            // 配置处理.sass/.scss文件的第三方loader规则
            { test: /\.s[a|c]ss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }

15、webpack中url-loader的使用

默认情况下,webpack无法处理CSS文件中的URL地址,不管是图片还是字体库,只要是URL地址,都处理不了

(1)npm i url-loader file-loader -D

file-loader是url-loader的内部依赖

            // 配置处理图片路径的loader
            { test: /\.(jpg|jpeg|png|gif|bmp)$/, use: 'url-loader' }

这个时候审查发现,图片路径转码成base64格式了

(2)限制图片转码

可以给url-loader传参,限制图片转码为base64格式的字符串

            // 配置处理图片路径的loader
            { test: /\.(jpg|jpeg|png|gif|bmp)$/, use: 'url-loader?limit=15735' }

limit给定的值,是图片的大小,单位是byte,如果引用的图片大小,大于等于给定的limit值,则不会被转码为base64格式的字符串,如果图片小于给定的limit值,则会被转码为base64格式的字符串

但是我们发现,此时URL中图片名称不是我们引入的图片名称,这是webpack打包的时候,为了防止图片的重名,自动为每一个图片生成一个hash值作为图片名

(3)设置打包时,图片名称不变

 // 配置处理图片路径的loader
{ test: /\.(jpg|jpeg|png|gif|bmp)$/, use: 'url-loader?limit=15735&name=[name].[ext]' }

传递另一个参数name,[name]表示引入的图片名称是啥,打包后就是啥,[ext]表示引入的图片后缀是啥,打包后还是啥。

但是这种情况下存在一个问题就是:如果存在不同路径下的重名的图片,打包后,后面的图片会把前面的同名图片覆盖掉

(4)设置打包后的图片名称

// 配置处理图片路径的loader
{ test: /\.(jpg|jpeg|png|gif|bmp)$/, use: 'url-loader?limit=15735&name=[hash:8]-[name].[ext]' }

[hash:8]-[name]表示打包后在每个图片名称不变,但在前面用短横线链接一个8位的hash值,防止图片名称。hash值最长32位

16、webpack中使用url-loader处理字体文件

(1)安装bootstrap3   npm install bootstrap@3

(2)在index.html中应用bootstrap中的图标

<span class="glyphicon glyphicon-heart" aria-hidden="true"></span>

(3)bootstrap中的图标依赖bootstrap.css,所以在main.js文件中引入bootstrap.css

// 如果通过路径形式引入node_modules中的相关文件,
// 可以直接省略路径前面的node_modules这一层目录,直接写包的名称,然后后面跟上具体的文件路径
// 不写node_modules ,会默认去node_modules下去找
import 'bootstrap/dist/css/bootstrap.css'

(4)bootstrap中的图标依赖bootstrap的字体文件,所以需要配置处理这些字体文件的

            // 配置处理字体文件的loader
            { test: /\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader' }

17、关于webpack和npm中几个问题的说明

注意:.json文件里面不能写注释

之前安装过包,会在package.json里面有记录,但不一定代表项目node_modules下就有这个包,如果运行报错,找不到相应的包,注意查看是否包不在了

18、webpack中babel的配置

在main.js中写以下几行代码

class Person {
    static info = {name: 'zs', age: 20 }
}
// 访问Person类身上的info静态属性
console.log(Person.info);

class关键字,是ES6中提供的新语法,是用来实现ES6中面向对象编程的方式

使用static关键字,可以定义静态属性,所谓静态属性,就是可以通过类名,直接访问的属性

实例属性:只能通过类的实例,来访问的属性,叫做实例属性

在webpack中,默认只能处理一部分ES6的新语法,一些更高级的ES6或者ES7语法,webpack是处理不了的,例如class定义的类;

这时候需要借助第三方的loader,帮助webpack处理这些高级的语法,当第三方loader把高级语法转为低级的语法之后,会把结果交给webpack去打包到bundle.js中。

通过Babel,可以将高级语法转换为低级语法

1.在webpack中,可以运行如下两套命令,安装两套包,去安装Babel相关的loader功能:

1.1 第一套包(Babel的转换工具): cnpm i babel-core babel-loader babel-plugin-transform-runtime -D

1.2 第二套包(Babel语法插件):cnpm i babel-preset-env babel-preset-stage-0 -D

2.打开webpack的配置文件,在module节点下的rules数组中,添加一个新的匹配规则:

2.1 { test:/\.js$/, use: 'babel-loader', exclude:/node_modules/ }

            // 配置Babel来转换高级的ES语法
            { test:/\.js$/, use: 'babel-loader', exclude:/node_modules/ }

2.2 注意:在配置babel的loader 规则的时候,必须把node_modules目录,通过exclude选项排除掉,原因有二:

2.2.1 如果不排除掉node_modules,Babel会把node_modules中所有的第三方JS文件,都打包编译,这样,会非常消耗CPU,同时打包速度非常慢;

2.2.2 就算Babel把所有node_modules中的JS转换完毕,项目也无法正常运行。

3. 在项目根目录中,新建一个叫做.babelrc的Babel配置文件,这个配置文件属于JSON格式,所以在写Babel配置文件的时候,必须符合JSON语法规范:不能写注释,字符串必须用双引号

3.1 在.babelrc配置文件中,写如下配置:

{
    "presets": [ "env", "stage-0" ],
    "plugins": [ "transform-runtime" ]
}

最终的webpack配置文件

// webpack.config.js
const path = require('path')

// 导入在内存中生成HTML页面的插件
// 只要是插件,都一定要放到plugins节点中去
const htmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    // 入口:表示要使用webpack打包哪个文件
    entry: path.join(__dirname, './src/main.js'),
    // 出口:输出文件的相关配置
    output: {
        // 指定打包好的文件,输出到哪个目录中去
        path: path.join(__dirname, './dist'),
        // 指定输出的文件名称
        filename: 'bundle.js'
    },
    // 配置插件的节点,是一个数组
    plugins: [
        // 创建一个在内存中生成HTML页面的插件
        new htmlWebpackPlugin({
            // 指定模板页面,将来会根据指定的模板路径,去生成内存中的页面
            template: path.join(__dirname, './src/index.html'),
            // 指定生成的页面的名称
            filename: 'index.html'
        })
    ],
    // 这个节点,用于配置 所有第三方模块加载器
    module: {
        // 所有第三方模块的 匹配规则
        rules: [
            // 配置处理.css文件的第三方loader规则
            { test: /\.css$/, use: ['style-loader', 'css-loader']},
            // 配置处理.less文件的第三方loader规则
            { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
            // 配置处理.sass/.scss文件的第三方loader规则
            { test: /\.s[a|c]ss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
            // 配置处理图片路径的loader
            { test: /\.(jpg|jpeg|png|gif|bmp)$/, use: 'url-loader?limit=15735&name=[hash:8]-[name].[ext]' },
            // 配置处理字体文件的loader
            { test: /\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader' },
            // 配置Babel来转换高级的ES语法
            { test:/\.js$/, use: 'babel-loader', exclude:/node_modules/ }
        ]
    }
}

猜你喜欢

转载自blog.csdn.net/sleepwalker_1992/article/details/81149400