4

webpack

前言

  • 这篇文章是我在学习过程中对自己的一个记录和总结,也希望可以帮助到和我当初同样对webpack有困惑的小伙伴

  • 我在自学webpack时也参考了很多大神的文章,参考的帖子太多就不一一谢过了,再次感谢各位大神的帮助

  • 文章中的每个例子,我都是亲自测试过的,如果哪个地方出现笔误等问题还请大家批评,我会及时改正

  • 本文使用的webpack版本是V3.8.1


第一章 webpack能做什么

简介

现如今前端主流的三种框架VueJs、ReactJs、AngularJs都推荐与webpack共同使用,所以不管你是哪种技术路线都不得不去学习了解webpack。那么webpack到底是何方神圣?

官方说法是webpack是一个模块打包机,我个人理解是它可以把我们在开发环境下的代码以及依赖文件等打包成在生产环境下可以直接使用的文件。也可以把一些浏览器不能直接运行的文件进行转化,比如是css、less、scss等。同时webpack也可以对代码进行优化,比如压缩、合并、文件缓存等等。在项目中我们只需要把相应的配置文件配置好,那么接下来的工作就都可以交给webpack这个全能大神去完成了。

image

官方网站

英文: http://webpack.js.org/

中文:https://doc.webpack-china.org/

Github:https://github.com/webpack/we...


第二章 webpack安装

全局安装

npm install –g webpack

查看版本号

webpack -v

注意:全局安装并不推荐,因为全局安装以后版本就固定了,比如当前你全局安装了V3.8.1这个版本的webpack,如果你需要运行一个比较早期版本的项目,比如webpack2的项目,就会有问题。另外,如果当前项目你使用V3.8.1版本写的,如果有一天webpack的版本升级了,比如升级到了V4.X,那么你之前的项目很有可能就跑不起来了。所以并不建议全局安装,而是建议项目安装。

项目安装

进入项目所在目录:

npm init
npm install --save-dev webpack

注意:

  1. npm init 命令的目的是生成 package.json文件

  2. mac需要在命令前面加: sudo

  3. 如果npm命令安装慢,可以使用cnpm(https://npm.taobao.org/)或者是yarn(https://yarnpkg.com/zh-Hans/

  4. 项目安装的话,webpack -v命令是查看不了版本号的,因为项目安装时webpack是被安装到node_modules里面的


第三章 开发环境与生产环境

初学者会有一个疑问,为什么有的时候安装依赖包的时候是--save-dev,而有的时候是--save,这两个有什么区别呢?什么时候包含dev呢?
这就需要搞清楚一个概念:开发模式生产模式

开发模式 --save-dev

项目在开发编码过程中还未上线使用就属于开发模式,该模式下代码不需要压缩、合并等。比如编写可以使用sass进行css预处理,使用ES6的语法来编写js代码。在开发模式下依赖的包安装的时候就需要使用--save-devdev表示开发的意思,使用--save-dev安装的依赖包,会安装在package.jsondevDependencies中,这些依赖包只在开发时候会使用到,在上线生成环境下就不需要了。

生产模式 --save

项目已经开发测试完成需要打包上线进行运营了,这时候就属于生产模式,改模式下的文件需要是最终浏览器可以直接解析的文件,不能再用如.scss.vue.jsx等这样的文件了。在生产模式下依赖的包安装的时候就需要使用--save,使用--save安装的依赖包,会安装在package.jsondependencies中,这些依赖包是最终在上线时候使用到的,比如jquery.jsvue.js等。

大家在开发过程中安装每个依赖包的时候,都一定先考虑这个包是只有开发模式下能用到,还是在生产模式下也需要用到,其实大家按照这个思路把下面的文章都看完,应该就可以对--save-dev--save有一个自己的理解了


第四章 Hello World

不管学习什么语言或工具,Hello World都是必不可少的。

目录结构

image

  • src:存放开发环境下的文件,也就是我们平时写的代码都在这里面

  • dist:存放生产环境下的文件,也就是打包后的文件,项目上线时把dist文件夹中的内容拷贝到服务器上就可以使用了

  • node_modules:是自动生成的存放依赖包的文件夹,使用npm install命令安装依赖包

在src目录下,新建文件helloworld.js

alert('Hello World!');

webpack.config.js

在src同级目录下,新建文件webpack.config.js

const path = require('path');
module.exports = {
    //入口文件的配置项
    entry: {
        hello: './src/helloworld.js'
    },
    //出口文件的配置项
    output: {
        path: path.resolve(__dirname, 'dist'),
        //[name]对应的是entry里面的属性名,当然也可以指定打包后的文件名称
        filename: '[name].js'
    },
    //模块,loader都是在这里面配置
    module: {},
    //插件
    plugins: []
};

在webpack中,最重要的就是webpack.config.js文件,几乎所有的配置项都需要在该文件中配置,该文件中最重要的四项分别是:entry(入口)、ouput(出口)、module(模块)、plugins(插件)。

path.resolve(__dirname, 'dist')是取到当前项目的路径下的dist文件夹,是nodejs的语法。

配置好webpack.config.js文件后,需要在package.json中配置scripts,之所以要配置build,是因为我们的webpack并不是全局安装的,而是项目安装的,项目安装的话webpack命令就被安装到了node_modules下面,所以需要配置才能找到该命令。

"scripts": {
    "build": "webpack --watch"
 }

执行命令进行打包:

npm run build

打包成功后,就会在dist文件夹下,自动生成hello.js文件。

--watch 可以实时监控改变自动打包

watchOptions: {
    // 检测时间间隔
    poll : 1000,
    // 防止重复导报,500毫秒以内不在重复打包
    aggregeateTimeout: 500,
    // 忽略的文件夹
    ignored: /node_modules/
}

第五章 webpack-dev-server

在webpack里可以配置服务,这样的好处是页面不再使用本地协议打开,而是通过服务打开,这样ajax等就可以正常使用了。同时,当我们修改代码并保存时,可以实时更新到页面上,提高开发效率。

在webpack.config.js文件中,在与entry等同级配置下增加devServer配置

const path = require('path');
module.exports = {
    //入口文件的配置项
    entry: {
        hello: './src/helloworld.js'
    },
    //出口文件的配置项
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
    },
    //模块,loader都是在这里面配置
    module: {},
    //插件
    plugins: [],
    devServer: {
        //设置目录结构
        contentBase: path.resolve(__dirname, 'dist'),
        //服务器的IP地址
        host: '127.0.0.1',
        //服务端压缩是否开启
        compress: true,
        //服务端口号
        port: 8081
    }
};

package.json文件中进行配置

"scripts": {
    "build": "webpack --watch",
    "server": "webpack-dev-server"
}

这样的话就可以通过npm run server来开启服务了,在地址栏里就可以根据devServer里的配置信息来访问你的网站了,比如按照我的配置的话我需要在浏览器地址栏输入:http://127.0.0.1:8081来访问我的网站。

第六章 HTML文件打包

在项目中,我们需要把src目录下的html文件进行打包,打包到dist目录下,这里我以单页面为例。在src目录下,创建index.html文件

需要安装html-webpack-plugin插件

npm install --save-dev html-webpack-plugin 

webpack.config.js中引入安装的插件

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
    //入口文件的配置项
    entry: {
        hello: './src/helloworld.js'
    },
    //出口文件的配置项
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
    },
    //模块,loader都是在这里面配置
    module: {},
    //插件
    plugins: [
        new HtmlWebpackPlugin({
            minify: {
                //移除html中的引号
                removeAttributeQuotes: true,
                //去掉html文件中的回车和空格
                collapseWhitespace: true
            },
            hash: true,
            template: './src/index.html'
        })
    ],
    devServer: {
        //设置目录结构
        contentBase: path.resolve(__dirname, 'dist'),
        //服务器的IP地址
        host: '127.0.0.1',
        //服务端压缩是否开启
        compress: true,
        //服务端口号
        port: 8081
    }
};

注意:所有的plugins(插件)都需要安装并在webpack.config.js文件中引入,然后才能使用。


第七章 CSS 文件打包

css打包

项目中,css文件需要进行打包,在入口js文件中通过import引入css文件

import css from './css/index.css'

css文件打包需要依赖两个包

style-loader:用来处理css文件中的url()等,url挂在到js中
css-loader:用来将css插入到页面的style标签 安装style-loader:npm

安装两个依赖包:

install --save-dev style-loader css-loader

webpack.config.js文件中进行配置

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

注意:这两个包的引入是有先后顺序的,一定要县引入style-loader然后再引入css-loader,因为两个文件有依赖关系。

执行命令进行打包:

npm run build

注意: 这时css文件中的代码会被打包到js里面

css文件分离

项目中大多数时候我们需要把css文件单独分离出来,而不是打包到js文件中,这时就需要依赖插件extract-text-webpack-plugin,安装插件

npm install --save-dev extract-text-webpack-plugin

webpack.config.js文件中引入插件

const ExtractTextPlugin = require("extract-text-webpack-plugin");
module: {
    rules: [
        {
            test: /\.css$/,
            use: ExtractTextPlugin.extract({
                fallback: "style-loader",
                use: ["css-loader"]
            })
        }
    ]
}

plugins中引入

plugins: [
    new HtmlWebpackPlugin({
        minify: {
            removeAttributeQuotes: true,
            collapseWhitespace: true
        },
        hash: true,
        template: './src/index.html'
    }),
    new ExtractTextPlugin("css/index.css")
]

css文件会分离出来,但如果css中引用的图片不是base64格式而是独立的图片文件, 这时候就会出现路径问题导致找不到图片地址,需要在output配置publicPath来解决,其中IP地址和端口号需要根据自己项目的实际情况来配置

output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js',
    publicPath: 'http://127.0.0.1:8081/'
}

第八章 JS代码压缩

项目上线后,js文件通常都是需要进行压缩的,这样可以减小文件体积加快加载速度,当然webpack中已经自带了uglifyjs-webpack-plugin 插件来实现js代码压缩功能。

const UglifyJSPlugin = require('uglifyjs-webpack-plugin');

webpack.config.js文件中的plugins中增加

plugins: [
    new HtmlWebpackPlugin({
        minify: {
            removeAttributeQuotes: true,
            collapseWhitespace: true
        },
        hash: true,
        template: './src/index.html'
    }),
    new ExtractTextPlugin("css/index.css"),
    new UglifyJSPlugin()
]

注意:使用npm run build命令可以打包成功,js文件也可以进行压缩,但是使用 npm run server开启dev server是就会报错,原因是当前还处于开发模式中,正常情况下开发模式是不需要进行js文件压缩的,所以会报错。等到真正上线在生产模式下也不可能会使用der server的。


第九章 图片打包

图片打包分为两节介绍,因为在网页开发中图片引用的方式主要是两种,一种是在css文件中作为背景图片background-image: url(xx.jpg),另一种是在html文件中使用标签引入<img src="xx.jpg"/>

CSS中引用的图片

需要依赖两个loader,分别是file-loaderurl-loader,当然也一定是需要先安装后使用了

npm install --save-dev file-loader url-loader

module中增加对图片的规则

{
    // 匹配图片文件后 缀名称。
    test: /\.(png|jpg|gif)/,
    // 指定使用的loader和配置参数
    use: [{
        loader: 'url-loader',
        options: {
            // 把小于5000B的文件打成Base64的格式写入JS,大于这个大小的图片文件会生成单独的图片文件,这个大小具体多少看实际项目要求,单位为B
            limit: 50000,
            // 图片输出到dist文件夹中的images文件夹中
            outputPath: 'images/'
        }
    }]
}

注意:在loader中我们只配置了url-loader而没有配置file-loader,原因是url-loader封装了file-loader。当文件大于limit中限制大小需要生成图片文件时,url-loader会调用file-loader进行处理,参数也会直接传给file-loader

HTML中引用的图片

需要依赖于html-withimg-loader

npm install html-withimg-loader --save-dev

module中增加对html文件的规则

{
    test: /\.(html|htm)$/i,
    use: ['html-withimg-loader']
}

第十章 SASS打包

什么是SASS?CSS 预处理器定义了一种新的语言,其基本思想是,用一 种专门的编程语言,为 CSS 增加了一些编程的特性,将 CSS 作为目标生成文件,然后开发者就只要使用这种语言 进行编码工作。
通俗的说,“CSS 预处理器用一种专门的编程语言,进行 Web 页面样式设计,然后再编译成正常的 CSS 文件,以供 项目使用。CSS 预处理器为 CSS 增加一些编程的特性,无 需考虑浏览器的兼容性问题”,例如你可以在 CSS 中使用
变量、简单的逻辑程序、函数等等在编程语言中的一些基 本特性,可以让你的 CSS 更加简洁、适应性更强、可读性
更佳,更易于代码的维护等诸多好处。
在开发过程中,使用扩展名为.scss的文件来编写css样式,但该文件并不能直接被浏览器解析,所以就需要编译为.css的文件,一般是使用sass 命令来进行编译,在webpack中使用loader来编译该文件。
安装loader

npm install --save-dev node-sass sass-loader

在js中引入编写好的.scss文件

import sass from './css/common.scss';

module中增加对scss文件的规则

{
    test: /\.scss$/,
    // use: ['style-loader', 'css-loader', 'sass-loader']
    use: ExtractTextPlugin.extract({
        fallback: "style-loader",
        use: ["css-loader", "sass-loader"]
    })
}

注意:CSS预处理不只有SASS,我这里只是以SASS为例来演示webpack对于css预处理的打包支持


第十一章 CSS3自动加前缀

我们经常会为css3的属性前缀而苦恼,-webkit--moz--ms--o-,一般都是通过http://www.caniuse.com来查询,现在有了webpack自动加前缀的功能妈妈就再也不用担心我的学习啦~~

npm install postcss-loader autoprefixer --save-dev 

在项目的根目录下创建文件postcss.config.js

module.exports = {
    plugins: [
        require('autoprefixer')
    ]
}

module中修改对于css文件的规则

{
    test: /\.css$/,
    use: ExtractTextPlugin.extract({
        fallback: "style-loader",
        use: [{
            loader: "css-loader",
            options: {
                importLoader: 1
            }
        }, "postcss-loader"]
    })
}

打包以后发现css3属性的前缀就可以自动加上啦啦啦~~


第十二章 babel

现在越来越多的项目已经采用ES6甚至ES7 ES8的新特性来编写代码了,但有些语法并不能直接被浏览器识别,这就需要转化成浏览器可以直接识别的代码,就需要用到babel

npm install --save-dev babel-core babel-loader babel-preset-env babel-preset-react

module中修改对于js jsx文件的规则

{
    test: /\.(js|jsx)$/,
    use: {
        loader: 'babel-loader',
        options: {
            presets: ['env', 'react']

        }
    }
}

打包成功会发现新语法已经转化为ES5的语法了


第十三章 打包注释

有的时候我们需要在文件中直接打包进去一些注释信息,webpack自带的BannerPlugin插件就可以帮我们实现这个功能。在plugins中增加

new webpack.BannerPlugin('成哥所有,翻版必究!'),

第十四章 打包第三方类库

项目中我们经常需要用到第三方类库,比如jquery vuejs等,这就需要我们进行相应的配置。
安装第三方类库,这里以jquery vuejs为例

npm install jquery vue --save 

plugins中增加

new webpack.optimize.CommonsChunkPlugin({
    name: ['jquery', 'vue'],
    filename: 'assets/js/[name].js',
    minChunks: 2
})

总结

webpack的入门指南算是总结完了,其实webpack的强大之处还远不止于此,我只是在自己实践中总结下来一些常用的功能,希望可以对入门webpack的小伙伴有所帮助。



谢小菜
185 声望17 粉丝