Webpack 3.X

Webpack的作用

  • 打包:可以把多个Javascript文件打包成一个文件,减少服务器压力和下载带宽。
  • 转换:把拓展语言转换成为普通的JavaScript,让浏览器顺利运行。
  • 优化:前端变的越来越复杂后,性能也会遇到问题,而WebPack也开始肩负起了优化和提升性能的责任。

图例:


Webpack 3.X_第1张图片
image.png

安装

前提是你已经安装node

//全局安装webpack
npm install -g webpack
//初始化
npm init
//项目目录安装webpack
npm install webpack --save-dev

全局安装并不推荐,因为在使用不同的webpack项目中,可能会导致构建失败

什么是开发环境和生产环境?
  • 开发环境:开发时需要的环境,这里指在开发时需要依赖的包
  • 生产环境:程序开发完成,开始运行后的环境,这里指要使项目运行,所需要的依赖包

一个DEMO

webpack {entry file} {destination for bundled file}
webpack src/entry.js dist/bundle.js

配置文件 : 入口和出口

module.exports={
    //入口文件的配置项
    entry:{},
    //出口文件的配置项
    output:{},
    //模块:例如解读CSS,图片如何转换,压缩
    module:{},
    //插件,用于生产模版和各项功能
    plugins:[],
    //配置webpack开发服务功能
    devServer:{}
}
  • entry:配置入口文件的地址,可以是单一入口,也可以是多入口。
  • output:配置出口文件的地址,在webpack2.X版本后,支持多出口配置。
  • module:配置模块,主要是解析CSS和图片转换压缩等功能。
  • plugins:配置插件,根据你的需要配置不同功能的插件。
  • devServer:配置开发服务功能
//入口文件的配置项
entry:{
    //里面的entry是可以随便写的
    entry:'./src/entry.js'
},
//出口文件的配置项
output:{
    //打包的路径
    path:path.resolve(__dirname,'dist'),    //获取绝对路径
    //打包的文件名称
    filename:'bundle.js'
    
}

需要引入path

const path = require('path');

现在的webpack.config.js代码

const path = require('path');
module.exports={
    //入口文件的配置项
    entry:{
        entry:'./src/entry.js'
    },
    //出口文件的配置项
    output:{
        //输出的路径,用了Node语法
        path:path.resolve(__dirname,'dist'),
        //输出的文件名称
        filename:'bundle.js'
    },
    //模块:例如解读CSS,图片如何转换,压缩
    module:{},
    //插件,用于生产模版和各项功能
    plugins:[],
    //配置webpack开发服务功能
    devServer:{}
}
多入口,多出口
const path = require('path');
module.exports={
    //入口文件的配置项
    entry:{
        entry:'./src/entry.js',
        //这里我们又引入了一个入口文件
        entry2:'./src/entry2.js'
    },
    //出口文件的配置项
    output:{
        //输出的路径,用了Node语法
        path:path.resolve(__dirname,'dist'),
        //输出的文件名称
        filename:'[name].js'
    },
    //模块:例如解读CSS,图片如何转换,压缩
    module:{},
    //插件,用于生产模版和各项功能
    plugins:[],
    //配置webpack开发服务功能
    devServer:{}
}

[name]的意思是根据入口文件的名称,打包成相同的名称,有几个入口文件,就可以打包出几个文件。

配置文件 : 服务和热更新

设置webpack-dev-server

先安装webpack-dev-server

devServer:{
    //设置基本目录结构
    contentBase:path.resolve(__dirname,'dist'),
    //服务器的IP地址,可以使用IP也可以使用localhost
    host:'localhost',
    //服务端压缩是否开启
    compress:true,
    //配置服务端口号
    port:9898
}
  • contentBase:配置服务器基本运行路径,用于找到程序打包地址。
  • host:服务运行地址,建议使用本机IP
  • compress:服务器端压缩选型,一般设置为开启
  • port:服务运行端口
支持热更新

在npm run server 启动后,它是有一种监控机制的(也叫watch)。它可以监控到我们修改源码,并立即在浏览器里给我们更新。

//package.json
"scripts": {
    "server":"webpack-dev-server"
 },

打包CSS文件

Loaders
  • 可以把SASS文件的写法转换成CSS,而不在使用其他转换工具。
  • 可以把ES6或者ES7的代码,转换成大多浏览器兼容的JS代码。
  • 可以把React中的JSX转换成JavaScript代码。

所有的Loaders都需要在npm中单独进行安装,并在webpack.config.js里进行配置。

  • test:用于匹配处理文件的扩展名的表达式,这个选项是必须进行配置的;
  • use:loader名称,就是你要使用模块的名称,这个选项也必须进行配置,否则报错;
  • include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
  • query:为loaders提供额外的设置选项(可选)。

CSS文件建立好后,需要引入到入口文件中,才可以打包到

/src/entry.js
import css from './css/index.css';

安装loader

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

loaders配置

//webpack.config.js
module:{
    rules:[
        {
            test:/\.css$/,
            use:['style-loader','css-loader']
        }
    ]
},
loader的三种写法
//use
module:{
    rules:[
        {
            test:/\.css$/,
            use:['style-loader','css-loader']
        }
    ]
},
//loader
module:{
    rules:[
        {
            test:/\.css$/,
            loader:['style-loader','css-loader']
        }
    ]
},
//use+loader
module:{
    rules:[
        {
            test:/\.css$/,
            use: [
                {
                    loader: "style-loader"
                }, {
                    loader: "css-loader"
                }
            ]
        }
    ]
},

压缩JS代码

虽然uglifyjs是插件,但是webpack版本里默认已经集成,不需要再次安装。

//webpack.config.js
//引入
const uglify = require('uglifyjs-webpack-plugin');
//配置插件
plugins:[
    new uglify()
],

现在的webpack.config.js

const path=require('path');
const uglify = require('uglifyjs-webpack-plugin');
module.exports={
    entry:{
        entry:'./src/entry.js',
        entry2:'./src/entry2.js'
    },
    output:{
        path:path.resolve(__dirname,'dist'),
        filename:'[name].js'
    },
    module:{
        rules:[
            {
                test:/\.css$/,
                use: ["style-loader", "css-loader"]
            }
        ]
    },
    plugins:[
        new uglify()
    ],
    devServer:{
       contentBase:path.resolve(__dirname,'dist'),
       host:'192.168.0.104',
       compress:true,
       port:1717
    }
}

HTML文件的发布

在之前,html文件应该是在src目录下的.


Webpack 3.X_第2张图片
image.png
  1. 先把html文件放入到src目录下
  2. 配置webpack.config.js文件,先引入html-webpack-plugin插件。
const htmlPlugin= require('html-webpack-plugin');
  1. npm安装
npm install --save-dev html-webpack-plugin
  1. webpack.config.js配置
plugins:[
    new htmlPlugin({
        minify:{
            removeAttributeQuotes:true
        },
        hash:true,
        template:'./src/index.html'
    })
],
  • minify:是对html文件进行压缩,removeAttrubuteQuotes是却掉属性的双引号。
  • hash:为了开发中js有缓存效果,所以加入hash,这样可以有效避免缓存JS。
  • template:是要打包的html模版路径和文件名称。

html文件的打包可以有效的区分开发目录和生产目录

图片处理

CSS中的图片处理

  1. css中写入一些图片的样式
#tupian{
   background-image: url(../images/manhua.png);
   width:466px;
   height:453px;
}
  1. 安装file-loader和url-loader
npm install --save-dev file-loader url-loader

file-loader:解决引用路径的问题,拿background样式用url引入背景图来说,我们都知道,webpack最终会将各个模块打包成一个文件,因此我们样式中的url路径是相对入口html页面的,而不是相对于原始css文件所在的路径的。这就会导致图片引入失败。这个问题是用file-loader解决的,file-loader可以解析项目中的url引入(不仅限于css),根据我们的配置,将图片拷贝到相应的路径,再根据我们的配置,修改打包后文件引用路径,使之指向正确的文件。

url-loader:如果图片较多,会发很多http请求,会降低页面性能。这个问题可以通过url-loader解决。url-loader会将引入的图片编码,生成dataURl。相当于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了。当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的还会使用file-loader进行copy。

  1. 配置url-loader
//webpack.config.js文件
module:{
    rules:[
        {
            test:/\.css$/,
            use:['style-loader','css-loader']
        },
        {
            test:/\.(png|jpg|gif)$/,
            use:[{
                loader:'url-loader',
                options:{
                    limit:5000,
                    outputPath:'images/'
                }
            }]
        }
    ]
},
  • test:/.(png|jpg|gif)/是匹配图片文件后缀名称。
  • use:是指定使用的loader和loader的配置参数。
  • limit:是把小于5000B的文件打成Base64的格式,写入JS。
  • outputPath : 将图片放入指定的路径下
url-loader和file-loader的关系

url-loader封装了file-loader。url-loader不依赖于file-loader,即使用url-loader时,只需要安装url-loader即可,不需要安装file-loader,因为url-loader内置了file-loader。通过上面的介绍,我们可以看到,url-loader工作分两种情况:
1.文件大小小于limit参数,url-loader将会把文件转为DataURL(Base64格式);
2.文件大小大于limit,url-loader会调用file-loader进行处理,参数也会直接传给file-loader。

CSS分离与图片路径处理

CSS分离:extract-text-webpack-plugin
  1. 安装
npm install --save-dev extract-text-webpack-plugin
  1. 引入
const extractTextPlugin = require("extract-text-webpack-plugin");
  1. 设置plugins,只需要new一下这个对象就可以了
new extractTextPlugin("css/index.css")
  1. 修改原来的style-loader和css-loader。
module:{
    rules:[
        {
            test:/\.css$/,
            use: extractTextPlugin.extract({
                fallback:"style-loader",
                use:"css-loader"
            })
        },
        {
            test:/\.(png|jpg|gif)$/,
            use:[{
                loader:'url-loader',
                options:{
                    limit:5000,
                    outputPath:'images/'
                }
            }]
        }
    ]
},
图片路径问题

利用extract-text-webpack-plugin插件很轻松的就把CSS文件分离了出来,但是CSS路径并不正确,使用publicPath解决

publicPath:是在webpack.config.js文件的output选项中,主要作用就是处理静态文件路径的。

//webpack.config.js
//声明一个对象
var website ={
    publicPath:"http://192.168.1.108:1717/"
}
//引用这个对象的属性
output : {
    path:path.resolve(__dirname,'dist'),
    filename: '[name].js',
    publicPath:website.publicPath
},

处理HTML中的图片

html-withimg-loader
  1. 安装
npm install html-withimg-loader --save-dev
  1. 配置loader
//webpack.config.js
{
    test: /\.(htm|html)$/i,
     use:[ 'html-withimg-loader'] 
}

CSS进阶

打包Less

  1. 安装
//安装less服务
npm install less --save-dev
//安装less-loader
npm install less-loader --save-dev
  1. 写loader配置
//webpack.config.js
{
    test: /\.less$/,
    use: [{
           loader: "style-loader" // creates style nodes from JS strings
        }, {
            loader: "css-loader" // translates CSS into CommonJS
        , {
            loader: "less-loader" // compiles Less to CSS
        }]
}
  1. 引入到入口文件中
import less from './less/black.less';
把less分离
{
    test:/\.less$/,
    use:extractTextPlugin.extract({
        use:[{
            loader:"css-loader"
        },{
            loader:"less-loader"
        }],
        fallback:"style-loader"
    })
}

SASS的打包和分离

和Less非常相似

npm install node-sass sass-loader --save-dev
//webpack.config.js
{
    test:/\.scss$/,
    use:extractTextPlugin.extract({
        use:[{
            loader:"css-loader"
        },{
            loader:"sass-loader"
        }],
        fallback:"style-loader"
    })
}

postcss自动添加CSS属性前缀

postcss
  1. 安装
npm install postcss-loader autoprefixer --save-dev
  1. 在项目根目录(和webpack.config.js同级)建立postcss.config.js
//postcss.config.js
module.exports = {
    plugins: [
        require('autoprefixer')
    ]
}
  1. 提取CSS的loader配置
{
    test: /\.css$/,
    use: extractTextPlugin.extract({
        fallback: 'style-loader',
        use: [
            { loader: 'css-loader', options: { importLoaders: 1 } },
            'postcss-loader'
        ]
    })
    
}

消除未使用的CSS

PurifyCSS-webpack
  1. 安装
    purifycss-webpack依赖于purify-css这个包
npm i purifycss-webpack purify-css -D
  1. 引入glob和purifycss-webpack
    同步检查模板,引入node的glob对象使用
//webpack.config.js
const glob = require('glob');
const purifyCssPlugin = require("purifycss-webpack");
  1. 配置plugins
    这里配置了一个paths,主要是需找html模板,purifycss根据这个配置会遍历你的文件,查找哪些css被使用了。
//webpack.config.js
plugins:[
    //new uglify() 
    new htmlPlugin({
        minify:{
            removeAttrubuteQuotes:true
        },
        hash:true,
        template:'./src/index.html'
        
    }),
    new extractTextPlugin("css/index.css"),
    new PurifyCSSPlugin({
        // Give paths to parse for rules. These should be absolute!
        paths: glob.sync(path.join(__dirname, 'src/*.html')),
        })
 
]

使用这个插件必须配合extract-text-webpack-plugin这个插件

给webpack增加babel支持

Babel

Babel其实是一个编译JavaScript的平台,它的强大之处表现在可以通过便宜帮你达到以下目的:

  • 使用下一代的javaScript代码(ES6,ES7….),即使这些标准目前并未被当前的浏览器完全支持。
  • 使用基于JavaScript进行了扩展的语言,比如React的JSX。

Babel的安装与配置

Babel其实是几个模块化的包,其核心功能位于称为babel-core的npm包中,webpack可以把其不同的包整合在一起使用,对于每一个你需要的功能或拓展,你都需要安装单独的包(用得最多的是解析ES6的babel-preset-es2015包和解析JSX的babel-preset-react包)。

  1. 安装
npm i babel-core babel-loader babel-preset-env -D
  1. 在webpack中配置Babel的方法
{
    test:/\.(jsx|js)$/,
    use:{
        loader:'babel-loader',
        options:{
            presets:[
                "env"
            ]
        }
    },
    exclude:/node_modules/
}

现在打包的代码就是经过处理的了

.babelrc

虽然Babel可以直接在webpack.config.js中进行配置,但是考虑到babel具有非常多的配置选项,如果写在webapck.config.js中会非常的雍长不可阅读,所以把配置写在.babelrc文件里。

  1. 在项目根目录新建.babelrc文件,并把配置写到文件里。
//.babelrc
{
    "presets":["env"]
}
  1. webpack.config.js里的loader配置
{
    test:/\.js$/,
    use:{
        loader:'babel-loader',
    },
    exclude:/node_modules/
}

打包后的代码调试

使用了webpack后,所以代码都打包到了一起,给调试带来了麻烦,但是webpack已经为我们充分考虑好了这点,它支持生产Source Maps来方便我们的调试。在使用webpack时只要通过简单的devtool配置,webapck就会自动给我们生产source maps 文件,map文件是一种对应编译文件和源文件的方法,让我们调试起来更简单。

在配置devtool时,webpack给我们提供了四种选项。

  • source-map:在一个单独文件中产生一个完整且功能完全的文件。这个文件具有最好的source map,但是它会减慢打包速度;
  • cheap-module-source-map:在一个单独的文件中产生一个不带列映射的map,不带列映射提高了打包速度,但是也使得浏览器开发者工具只能对应到具体的行,不能对应到具体的列(符号),会对调试造成不便。
  • eval-source-map:使用eval打包源文件模块,在同一个文件中生产干净的完整版的sourcemap,但是对打包后输出的JS文件的执行具有性能和安全的隐患。在开发阶段这是一个非常好的选项,在生产阶段则一定要不开启这个选项。
  • cheap-module-eval-source-map:这是在打包文件时最快的生产source map的方法,生产的 Source map 会和打包后的JavaScript文件同行显示,没有影射列,和eval-source-map选项具有相似的缺点。

四种打包模式,有上到下打包速度越来越快,不过同时也具有越来越多的负面作用,较快的打包速度的后果就是对执行和调试有一定的影响。

实战

开发与生产并行设置

  1. 修改package.json命令
"scripts": {
  "start": "set type=dev&webpack-dev-server",
  "build": "set type=build&webpack"
},
  1. 修改webpack.config.js文件
if(process.env.type== "dev"){
    var website={
        publicPath:"http://localhost:9898/"
    }
    console.log( encodeURIComponent(process.env.type) );
}else{
    var website={
        publicPath:"http://www.guoqianchen.com/"
    }
    console.log( encodeURIComponent(process.env.type) );
}
  1. MAC下的package.json配置
    MAC电脑下需要把set换成export,并且要多加一个&符
"scripts": {
  "dev": "set type=dev&webpack-dev-server",
  "build": "set type=build&webpack",
  "dev_mac": "export type=dev&&webpack-dev-server",
  "build_mac": "export type=build&&webpack"
},

模块化

webpack.config.js要使用Common.js方式引入

打包第三方类库

引入jQuery
  1. 安装jquery
npm install jquery --save
  1. 引入到JS文件中
import $ from 'jquery'
用plugin引入

ProvidePlugin是一个webpack自带的插件,Provide的意思就是装备、提供。因为ProvidePlugin是webpack自带的插件,所以要先再webpack.config.js中引入webpack。

  1. webpack.config.js中引入webpack
const webpack = require('webpack');

在webpack.config.js里引入必须使用require,否则会报错的,这点小伙伴们一定要注意。

2.配置plugin模块

plugins:[
    new webpack.ProvidePlugin({
        $:"jquery"
    })
],

配置好后,就可以在你的入口文件中使用了,而不用再次引入了。这是一种全局的引入,在实际工作中也可以很好的规范项目所使用的第三方库。

watch的配置

watchOptions:{
    //检测修改的时间,以毫秒为单位
    poll:1000, 
    //防止重复保存而发生重复编译错误。这里设置的500是半秒内重复保存,不进行打包操作
    aggregeateTimeout:500, 
    //不监听的目录
    ignored:/node_modules/, 
}
webpack --watch

BannerPlugin插件

  1. 配置plugins
new webpack.BannerPlugin('hello')

在使用这个插件之前必须引入webpack。

const webpack = require('webpack');

你可能感兴趣的:(Webpack 3.X)