知识点前端路Webpack

webpack使用总结

2017-02-11  本文已影响3178人  iceman_dev

前言:

学习webpack的时候,看过它的官网,发现非常难懂,各种内容编排的很乱,并且挺生涩难懂的,和React Native等项目的官网比起来,差太多了,所以如果刚开始接触webpack的话,不建议直接去其官网看。

一、webpack介绍

1.1、什么是webpack

webpack是一个module bundler(模块打包工具),所谓的模块就是在平时的前端开发中,用到一些静态资源,如JavaScript、CSS、图片等文件,webpack就将这些静态资源文件称之为模块。

webpack支持AMD和CommonJS,以及其他的一些模块系统,并且兼容多种JS书写规范,可以处理模块间的以来关系,所以具有更强大的JS模块化的功能,它能对静态资源进行统一的管理以及打包发布,在官网中用这张图片介绍:

webpack官网的介绍.png

它在很多地方都能替代Grunt和Gulp,因为它能够编译打包CSS,做CSS预处理,对JS的方言进行编译,打包图片,代码压缩等等。所以在我接触了webpack之后,就不太想用gulp了。

1.2、为什么使用webpack

在自己的学习使用中、和技术交流群里以及和朋友的讨论、网上其他大神的博客中得到一些为什么要使用webpack的原因,webpack的优点,webpack更适用于哪里。

webpack最常用与spa应用,主要是vue和React,其实它就非常像Browserify,但是将应用打包为多个文件。如果单页面应用有多个页面,那么用户只从下载对应页面的代码. 当他么访问到另一个页面, 他们不需要重新下载通用的代码。

webpack也能用于服务端,但是构建后端代码一般都不会用webpack,坑太多了,所以正常情况下只用于前端,这是一个做了很多年前端的朋友告诉我的经验,所以别人已经走过的坑,还是不要去踩了~~~~ 并且我个人觉得后端其实也没必要这么做,因为后端更多的是处理逻辑,以及为前端提供数据.....

二、基本使用

2.1、webpack基本运行

2.1.1、创建基本项目结构

基本项目结构.png
基本项目结构.png

2.1.2、安装全局依赖:

npm  install  webpack  -g 

2.1.3、创建配置文件

在项目的根目录创建三个或多个webpack配置文件,我们创建两个:

2.1.4、修改配置文件

注意:开发环境和生产环境的配置是不一样的,具体配置上的差异看后面的内容。

首先先配置开发环境,写上最基本的内容:

var path = require('path');
module.exports = {
    entry:path.resolve(__dirname,'src/js/app.js'),
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: 'bundle.js',
    },
}

最基本的配置文件中一般含有文件入口和输出文件的配置信息,后期还可以加上loader和各种插件配置使用。

2.1.5、通过配置文件运行webpack

webpack

由于我们是将开发环境和发布环境分开的,并没有直接添加webpack.config.js,所以这种方式在我们这里显然是不行的;

webpack --config webpack.dev.config.js

命令行输出如下:

zhongfabindeMacBook-Pro:webpack_test zhongfabin$ webpack --config webpack.dev.config.js
Hash: d8151fcc7a02add3ec93
Version: webpack 2.2.1
Time: 49ms
    Asset     Size  Chunks             Chunk Names
bundle.js  2.57 kB       0  [emitted]  main
   [0] ./src/js/app.js 63 bytes {0} [built]

在dist中生成了bundle.js:


生成在dist中的bundle.js.png

这时候如果想看生成的js是否能用,我们需要将src中的拷贝一份到dist中,并且引入bundle.js(后面可以自动生成index,现在后没学到):


手动加入index.html.png
运行效果如下:
运行效果.png

注意:在实际的开发中,我们基本上不会用以上这种直接提供的命令,因为用这种方式,我们需要手动的敲打很多字母,在实际的开发中通用的方法都是使用配置文件的方式运行(接下来讲解)。

2.2、把运行命令配置到npm的script中

2.2.1、为什么加入到npm的script中

webpack-dev-server --devtool eval --progress --colors --hot --content-base build

所以我们不可能每次都敲这么长,因而我们就把这一大串配置到npm中

2.2.2、使用步骤

npm install --save-dev webpack 
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev":"webpack --config webpack.dev.config.js",
    "pub":"webpack --config webpack.pub.config.js"
},
npm run dev

这样之后就不要敲那么复杂的命令了。

2.3、为发布目录启动服务

我们没修改一次就要需要输入 npm run develop 是一件非常无聊的事情,幸运的是,我们可以把让他自己运行,那就是使用webpack-dev-server。

除了提供模块打包功能,Webpack还提供了一个基于Node.js Express框架的开发服务器,它是一个静态资源Web服务器,对于简单静态页面或者仅依赖于独立服务的前端页面,都可以直接使用这个开发服务器进行开发。在开发过程中,开发服务器会监听每一个文件的变化,进行实时打包,并且可以推送通知前端页面代码发生了变化,从而可以实现页面的自动刷新。

使用步骤:

npm install --save-dev webpack-dev-server
{
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "pub": "webpack --config webpack.pub.config.js",
        "dev": "webpack-dev-server  --config webpack.dev.config.js --devtool eval --progress --colors --hot --content-base src"
    }
}

在dev的配置中做了以上改变之后,webpack-dev-server 会在 localhost:8080 建立一个 Web 服务器。
几个参数的解释:

2.4、浏览器自动刷新

做完以上的所有步骤之后,可以启动一个服务并监听变化了,但是浏览器你还需要手动刷新一下,我们其实是可以通过下面的这个方法让它自动刷新的。

修改配置文件中的entry部分,当前entry的的值为:

entry:path.resolve(__dirname,'src/js/app.js')

将entry的值改为一个数组,除了上面的内容加进去之外,再加其他两句:

var path = require('path');
module.exports = {
    entry: [
        'webpack/hot/dev-server',
        'webpack-dev-server/client?http://localhost:8080',
        path.resolve(__dirname,'src/js/app.js')
    ],
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    }
}

特别注意:此时用webpack-dev-server生成bundle.js文件是在内存中的,所以在src中的index引入的js文件应该生成的bundle.js,如果还是引入的app.js的话,将会看不到刷新的效果。

修改js文件.png

三、常用的加载器

加载器就是webpack准备的一些预处理工具,比如编译jsx和es6的加载器,处理sass等....

使用加载器的步骤也很简单,首先是安装依赖,然后在配置文件的module中加一个字段module字段,在module写上loaders,在loaders中写上相应的配置。

3.1、编译jsx和ES6到原生js

npm install --save-dev babel-loader babel-core babel-preset-es2015  babel-preset-react 
module: {
    loaders: [
        {
            test: /\.jsx?$/, // 用正则来匹配文件路径,这段意思是匹配 js 或者 jsx
            loader: 'babel',// 加载模块 "babel" 是 "babel-loader" 的缩写
            query: {
                presets: ['es2015', 'react']
            }
        }
    ]
}

3.2、加载CSS

Webpack允许像加载任何代码一样加载 CSS。你可以选择你所需要的方式,但是你可以为每个组件把所有你的 CSS 加载到入口主文件中来做任何事情。

加载 CSS 需要 css-loader 和 style-loader,他们做两件不同的事情,css-loader会遍历 CSS 文件,然后找到 url() 表达式然后处理他们,style-loader 会把原来的 CSS 代码插入页面中的一个 style 标签中。

npm install --save-dev css-loader   style-loader
{
    test: /\.css$/,
    loader: 'style!css' // 如果有多个加载器,中间用感叹号隔开,多个加载器从右往左执行
}

“!”用来定义loader的串联关系,"-loader"是可以省略不写的,多个loader之间用“!”连接起来

import  './project-styles.css';

3.3、加载sass

npm  install  --save-dev  sass-loader
{
    test: /\.scss$/,
    loader: 'style!css!sass'
}

3.4、图片处理

直到 HTTP/2 你才能在应用加载的时候避免设置太多 HTTP 请求。根据浏览器不同你必须设置你的并行请求数,如果你在你的 CSS 中加载了太多图片的话,可以自动把这些图片转成 BASE64 字符串然后内联到 CSS 里来降低必要的请求数,这个方法取决与你的图片大小。你需要为你的应用平衡下载的大小和下载的数量,不过 Webpack 可以让这个平衡十分轻松适应。

npm  install  --save-dev url-loader file-loader
{
    test: /\.(png|jpeg|gif|jpg)$/,
    loader: 'url?limit=25000'
}

加载器会把需要转换的路径变成 BASE64 字符串,在其他的 Webpack 书中提到的这方面会把你 CSS 中的 “url()” 像其他 require 或者 import 来处理。意味着如果我们可以通过它来处理我们的图片文件。
url-loader 传入的 limit 参数是告诉它图片如果不大于 25KB 的话要自动在它从属的 css 文件中转成 BASE64 字符串。

div.img{
    background: url(../image/xxx.jpg)
}
//或者
var img = document.createElement("img");
img.src = require("../image/xxx.jpg");
document.body.appendChild(img);

你可以这样配置:

{
    test: /\.(png|jpeg|gif|jpg)$/,
    loader: 'file-loader?name=images/[name].[ext]'
}

针对上面的两种使用方式,loader可以自动识别并处理。根据loader中的设置,webpack会将小于指点大小的文件转化成 base64 格式的 dataUrl,其他图片会做适当的压缩并存放在指定目录中。

四、发布配置

前面一直都在捣鼓config webpack.dev.config.js,也就是一致都在配置开发环境,现在重要配置发布环境了,也就是配置config webpack.pub.config.js,其实发布的配置和开发的配置差不了太多。

4.1、基础配置

"pub": " webpack --config webpack.pub.config.js  -p",

指向生产的配置文件,并且加上了webpack的cli的-p,他会自动做一些优化

var path = require('path');
module.exports = {
    entry: path.resolve(__dirname, 'src/js/app.js'),
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    module: {
        loaders: [
            {
                test: /\.jsx?$/, 
                loader: 'babel',
                query: {
                    presets: ['es2015', 'react']
                }
            },
            {
                test: /\.css$/, 
                loader: 'style!css' 
            },
            {
                test: /\.scss$/,
                loader: 'style!css!sass'
            },
            {
                test: /\.(png|jpeg|gif|jpg)$/,
                loader: 'file-loader?name=images/[name].[ext]'
            },
        ]
    },
}

可以看到,其实生产环境的配置和开发的配置没有太大的不同,主要是把不需要的东西给去掉了。

4.2、分离应用和第三方

4.2.1、何时应该分离

当你的应用依赖其他库尤其是像 React JS 这种大型库的时候,你需要考虑把这些依赖分离出去,这样就能够让用户在你更新应用之后不需要再次下载第三方文件。当满足下面几个情况的时候你就需要这么做了:

4.2.2、修改配置文件

var webpack=require("webpack");

五、常用插件介绍

webpack提供了丰富的组件用来满足不同的需求,当然了我们也可以自行实现一个组件来满足自己的需求。

plugins: [
     //your plugins list
 ]

5.1、压缩插件

这个插件是webpack自带的

// 用webpack压缩代码,可以忽略代码中的警告
new webpack.optimize.UglifyJsPlugin({
    compress: {
        warnings: false
    }
}),

5.2、提取CSS插件

在webpack中编写js文件时,可以通过require的方式引入其他的静态资源,可通过loader对文件自动解析并打包文件。通常会将js 文件打包合并,css文件会在页面的header中嵌入style的方式载入页面。但开发过程中我们并不想将样式打在脚本中,最好可以独立生成css文件,以外链的形式加载。这时extract-text-webpack-plugin插件可以帮我们达到想要的效果。需要使用npm的方式加载插件,然后 参见下面的配置,就可以将js中的css文件提取,并以指定的文件名来进行加载。

npm install --save-dev extract-text-webpack-plugin
// 可以新建多个抽离样式的文件,这样就可以有多个css文件了。
new ExtractTextPlugin("app.css"),
plugins: [
    // 可以新建多个抽离样式的文件,这样就可以有多个css文件了。
    new ExtractTextPlugin("app.css"),
]

修改loaders中的配置:

{
    test: /\.css$/,
    loader: ExtractTextPlugin.extract('style-loader' , 'css-loader')
},

注意:我发现这个有一个问题,就是他只能把css抽出来,但是sass的样式不能分离出来。

5.3、新建index.html页面插件

npm install --save-dev html-webpack-plugin 
// 自动生成index.html页面插件
var HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
    new HtmlWebpackPlugin({
        template: './src/template.html',
        htmlWebpackPlugin: {
            "files": {
                "css": ["app.css"],
                "js": ["vendors.js","bundle.js"]
            }
        },
        minify: {
            removeComments: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true
        }
    }),
]

创建模板文件:template.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="keyword" content="webpack,gulp,git">
    <title>model</title>
</head>
<body>
<div id="app"></div>
</body>
</html>

5.4、自动打开浏览器插件

在开发环境中使用,run之后自动打开浏览器

npm install --save-dev open-browser-webpack-plugin
// 自动打开浏览器插件
var OpenBrowserPlugin = require('open-browser-webpack-plugin');
plugins: [
    new OpenBrowserPlugin({url: 'http://localhost:8080/'})
]

5.5、删除插件

在开发环境中使用,run之后自动打开浏览器

npm install --save-dev clean-webpack-plugin
// 删除文件夹
var CleanPlugin = require('clean-webpack-plugin');
plugins: [
    // 构建之前先删除dist目录下面的文件夹
    new CleanPlugin(['dist']),
]

5.6、去掉react中的警告

plugins: [
    new webpack.DefinePlugin({
        //去掉react中的警告,react会自己判断
        'process.env': {
            NODE_ENV: '"production"'
        }
    }),
]

个人公众号(icemanFE):分享更多的前端技术和生活感悟

个人公众号.png
上一篇 下一篇

猜你喜欢

热点阅读