常见loader使用

2019年11月10日 阅读数:70
这篇文章主要向大家介绍常见loader使用,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

一、raw-loader(文件原始内容转换器)

一个能够用于加载文件做为字符串使用的加载器,使用UTF-8编码。javascript

控制台输入:
npm i --D raw-loader

1.二、使用loader的三种方式

(1)、配置(推荐):在 webpack.config.js 文件中指定 loadercss

module.rules 容许你在 webpack 配置中指定多个 loader。 这是展现 loader 的一种简明方式,而且有助于使代码变得简洁。同时让你对各个 loader 有个全局概览:html

复制代码
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          { loader: 'style-loader' },
          {
            loader: 'css-loader',
            options: {
              modules: true
            }
          }
        ]
      }
    ]
  }
复制代码

Loaders须要单独安装而且须要在webpack.config.js中的modules关键字下进行配置,Loaders的配置包括如下几方面:前端

复制代码
test:一个用以匹配loaders所处理文件的拓展名的正则表达式(必须)

loader:loader的名称(必须)

include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不须要处理的文件(文件夹)(可选)

query:为loaders提供额外的设置选项(可选)
复制代码

(2)、内联:在每一个 import 语句中显式指定 loadervue

能够在 import 语句或任何等效于 "import" 的方式中指定 loader。使用 ! 将资源中的 loader 分开。分开的每一个部分都相对于当前目录解析。java

import Styles from 'style-loader!css-loader?modules!./styles.css';

经过前置全部规则及使用 !,能够对应覆盖到配置中的任意 loader。node

选项能够传递查询参数,例如 ?key=value&foo=bar,或者一个 JSON 对象,例如 ?{"key":"value","foo":"bar"}。react

尽量使用 module.rules,由于这样能够减小源码中的代码量,而且能够在出错时,更快地调试和定位 loader 中的问题。webpack

(3)、CLI:在 shell 命令中指定它们git

你也能够经过 CLI 使用 loader:

webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'

这会对 .jade 文件使用 jade-loader,对 .css 文件使用 style-loader 和 css-loader。

4.三、常见的loader

4.3.一、文件

  • raw-loader 加载文件原始内容(utf-8)
  • val-loader 将代码做为模块执行,并将 exports 转为 JS 代码
  • url-loader 像 file loader 同样工做,但若是文件小于限制,能够返回 data URL
  • file-loader 将文件发送到输出文件夹,并返回(相对)URL

4.3.二、JSON

4.3.三、转换编译(Transpiling)

4.3.四、模板(Templating)

  • html-loader 导出 HTML 为字符串,须要引用静态资源
  • pug-loader 加载 Pug 模板并返回一个函数
  • jade-loader 加载 Jade 模板并返回一个函数
  • markdown-loader 将 Markdown 转译为 HTML
  • react-markdown-loader 使用 markdown-parse parser(解析器) 将 Markdown 编译为 React 组件
  • posthtml-loader 使用 PostHTML 加载并转换 HTML 文件
  • handlebars-loader 将 Handlebars 转移为 HTML
  • markup-inline-loader 将内联的 SVG/MathML 文件转换为 HTML。在应用于图标字体,或将 CSS 动画应用于 SVG 时很是有用。

4.3.五、样式

  • style-loader 将模块的导出做为样式添加到 DOM 中
  • css-loader 解析 CSS 文件后,使用 import 加载,而且返回 CSS 代码
  • less-loader 加载和转译 LESS 文件
  • sass-loader 加载和转译 SASS/SCSS 文件
  • postcss-loader 使用 PostCSS 加载和转译 CSS/SSS 文件
  • stylus-loader 加载和转译 Stylus 文件

4.3.六、清理和测试(Linting && Testing)

4.3.七、框架(Frameworks)

  • vue-loader 加载和转译 Vue 组件
  • polymer-loader 使用选择预处理器(preprocessor)处理,而且 require() 相似一等模块(first-class)的 Web 组件
  • angular2-template-loader 加载和转译 Angular 组件

4.四、raw-loader(文件原始内容转换器)

一个能够用于加载文件做为字符串使用的加载器,使用UTF-8编码。

安装

npm i --D raw-loader

 安装结果:

用法一:

经过 webpack 配置、命令行或者内联使用 loader。

复制代码
webpack.config.js

module.exports = {
    module: {
        rules: [
            {
                test: /\.txt$/,
                use: 'raw-loader'
            }
        ]
    }
}
复制代码

在你的项目中

import txt from './file.txt';

用法二:经过命令行(CLI)

webpack --module-bind 'txt=raw-loader'

用法三:在你的项目中

import txt from 'file.txt';

内联使用

import txt from 'raw-loader!./file.txt';

示例:

webpack.config.json

  View Code

src/file1.txt

A loader for webpack that lets you import files as a string.

src/bar.js

复制代码
//定义模块
//部分依赖lodash中的join方法
import {join} from 'lodash';
//导入模块,得到file1.txt中的文件内容,被raw-loader处理
import message from './file1.txt';

//导出一个默认模块
export default function bar() {
    function component() {
        //建立DOM元素
        var element=document.createElement("h2");
        //使用join链接数组将结果写入元素的html中
        element.innerHTML=join(['Hello','Webpack','!'],' ')+"<br/>"+message;
        return element;
    }
    //在body中添加子元素
    document.body.appendChild(component());
}
复制代码

运行结果:

内联使用模块处理器:

4.五、CSS Loader(样式处理)

webpack提供两个工具处理样式表,css-loader 和 style-loader,两者处理的任务不一样,css-loader使你可以使用相似@import 和 url(...)的方法实现 require()的功能,style-loader将全部的计算后的样式加入页面中,两者组合在一块儿使你可以把样式表嵌入webpack打包后的JS文件中。

  • css-loader: 加载.css文件
  • style-loader:使用<style>将css-loader内部样式注入到咱们的HTML页面

css-loader详解:

https://www.npmjs.com/package/css-loader

https://www.webpackjs.com/loaders/css-loader/

style-loader详解:

https://www.npmjs.com/package/style-loader

https://www.webpackjs.com/loaders/style-loader/

4.5.一、安装

//安装
npm i style-loader css-loader -D

4.5.二、配置

复制代码
const path = require("path");

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: "bundle.js"
    },
    module: {
        rules: [
            {
                test:/\.css/,
                use:['style-loader',{
                    loader: 'css-loader',
                    options: {
                        sourceMap:true
                    }
                }]
            }
        ]
    },
    mode: "development"
};
复制代码

4.5.三、定义样式与引用

base.css

复制代码
h2{
    height: 40px;
    line-height: 40px;
    background: crimson;
    color:#fff;
}
复制代码

bar.js

复制代码
import {join} from 'lodash';
import base from '../css/base.css';

export default function bar() {
    function component() {
        var element=document.createElement("h2");
        element.innerHTML=join(['Hello','Webpack!']);
        return element;
    }
    document.body.appendChild(component());
}
复制代码

4.5.四、打包运行

打包:

运行:

生成代码:

4.5.五、注意事项

  1. rules里的数据类型为对象,每个loader都是一个对象
  2. test表示loader要处理什么类型的文件,这里用了一个正则去匹配文件类型
  3. use表示要使用哪一个loader,它的值是个数组,loader的使用顺序是从后往前
  4. 这个loader的意思为,在入口文件里找到.css类型的文件,先拿css-loader去处理成浏览器认识的css,再拿style-loader把处理后的css放在页面的style标签里

4.六、sass-loader(加载和转译 SASS/SCSS 文件)

加载sass或scss文件并转译成css

用css-loader或raw-loader 转换成一个JS模块或用ExtractTextPlugin插件将样式分隔成一个单独文件。

安装

npm i sass-loader node-sass --D

 

node-sass 和 webpack 是 sass-loader 的 peerDependency,所以可以精确控制它们的版本。

示例

css/baseScss.scss

复制代码
$height:50px;
$color:#3366ff;

h2{
  background: $color;
  height: $height;
  line-height: $height;
  color: white;
  padding-left: $height/5;
}
复制代码

 

经过将 style-loader 和 css-loader 与 sass-loader 链式调用,能够马上将样式做用在 DOM 元素。

配置webpack.config.json

复制代码
//webpack配置文件

//依赖node中的path模块
var path=require('path');

//定义一个默认模块对象
module.exports={
    //指定入口文件的位置,多入口
    entry:{
        index:"./src/index.js",
        main:"./src/main.js"
    },
    //设置输出结果
    output: {
        //路径,将相对路径转绝对路径
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模块名称,占位
        filename: "[name].bundle.js"
    },
    module: {  //模块处理
        rules: [ //处理器
            {
                test:/\.txt$/,  //当模块的后缀为.txt时匹配
                use: "raw-loader"  //模块转换器,能够以对象的形式指定参数
            },
            {
                test:/\.css$/,  //匹配全部css模块
                //use表示要使用哪一个loader,它的值是个数组,loader的使用顺序是从后往前
                use: ["style-loader",{
                    loader: "css-loader",  //转换器名称
                    options: {  //配置选项
                        modules:true,  //模块化
                        sourceMap:true  //是否生成调试文件
                    }
                }]  //使用多个模块转换器
            },
            {
                test: /\.scss$/,
                use: [{
                    loader: "style-loader" // 将 JS 字符串生成为 style 节点
                }, {
                    loader: "css-loader" // 将 CSS 转化成 CommonJS 模块
                }, {
                    loader: "sass-loader" // 将 Scss 编译成 CSS
                }]
            }
        ]
    },
    mode: "development"
};
复制代码

 

导入scss做为模块

复制代码
//定义模块
//部分依赖lodash中的join方法
import {join} from 'lodash';
//导入模块,得到file1.txt中的文件内容,被raw-loader处理
import message from './file1.txt';
//导入样式文件
//import '../css/baseCss.css'
//导入预处理样式文件
import '../css/baseScss.scss'

//导出一个默认模块
export default function bar() {
    function component() {
        //建立DOM元素
        var element=document.createElement("h2");
        //使用join链接数组将结果写入元素的html中
        element.innerHTML=join(['Hello','Webpack','!'],' ')+"<br/>"+message;
        return element;
    }
    //在body中添加子元素
    document.body.appendChild(component());
}
复制代码

打包后运行结果:

一般,生产环境下比较推荐的作法是,使用 ExtractTextPlugin 将样式表抽离成专门的单独文件。这样,样式表将再也不依赖于 JavaScript:

复制代码
const ExtractTextPlugin = require("extract-text-webpack-plugin");

const extractSass = new ExtractTextPlugin({
    filename: "[name].[contenthash].css",
    disable: process.env.NODE_ENV === "development"
});

module.exports = {
    ...
        module
:
{
    rules: [{
        test: /\.scss$/,
        use: extractSass.extract({
            use: [{
                loader: "css-loader"
            }, {
                loader: "sass-loader"
            }],
// 在开发环境使用 style-loader
            fallback: "style-loader"
        })
    }]
}
,
plugins: [
    extractSass
]
}
;
复制代码

4.七、url-loader(路径处理器)

 Webpack 容许你在js文件中require图片 , 经过 url-loader和file-loader来预处理图片文件,将图片转换成base64编码。

安装

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

用法

url-loader 功能相似于 file-loader,可是在文件大小(单位 byte)低于指定的限制时,能够返回一个 DataURL。

import img from './image.png'

配置

复制代码
webpack.config.js

module.exports = {
    module: {
        rules: [
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 8192
                        }
                    }
                ]
            }
        ]
    }
}
复制代码

示例

webpack.config.js

复制代码
//webpack配置文件

//依赖node中的path模块
var path=require('path');

//定义一个默认模块对象
module.exports={
    entry:{app01:"./src/app01.js"},
    //设置输出结果
    output: {
        //路径,将相对路径转绝对路径
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模块名称,占位
        filename: "[name].bundle.js"
    },
    module: {
        rules: [
            {
                //如是文件名是gif,jpg,jpeg,bmp图片则匹配,不分大小写
                test:/\.(gif|jpe?g|png|bmp)/i,
                use: {
                    loader: "url-loader",
                    options: {
                        //若是图片的大小小于1024byte(B)时转换成dataUrl,base64编码
                        limit:1024,
                        fallback:"responsive-loader"
                    }
                }
            }
        ]
    }
};
复制代码

src/app01.js

复制代码
//导入大图片 404byte
import srcBig from '../img/big.jpg';
//导入小图片 100Kbyte
import srcSma from '../img/small.gif';

console.log(srcBig);
console.log(srcSma)

alert("Hello App01!");

//建立大图片DOM
var img1=document.createElement("img");
//指定url
img1.src=srcBig;
//添加到文档中
document.body.appendChild(img1);

//建立小图片DOM
var img2=document.createElement("img");
//指定url
img2.src=srcSma;
//添加到文档中
document.body.appendChild(img2);
复制代码

运行结果:

5、插件plugins

5.一、插件概要

Plugin 是用来扩展 Webpack 功能的,经过在构建流程里注入钩子实现,它给 Webpack 带来了很大的灵活性。

插件是 webpack 的支柱功能。webpack 自身也是构建于,你在 webpack 配置中用到的相同的插件系统之上!插件目的在于解决 loader 没法实现的其余事。

webpack 插件是一个具备 apply 属性的 JavaScript 对象。apply 属性会被 webpack compiler 调用,而且 compiler 对象可在整个编译生命周期访问。

复制代码
ConsoleLogOnBuildWebpackPlugin.js

const pluginName = 'ConsoleLogOnBuildWebpackPlugin';

class ConsoleLogOnBuildWebpackPlugin {
    apply(compiler) {
        compiler.hooks.run.tap(pluginName, compilation => {
            console.log("webpack 构建过程开始!");
        });
    }
}
复制代码

 

compiler hook 的 tap 方法的第一个参数,应该是驼峰式命名的插件名称。建议为此使用一个常量,以便它能够在全部 hook 中复用。

因为插件能够带参数/选项,你必须在 webpack 配置中,向 plugins 属性传入 new 实例。

根据你的 webpack 用法,这里有多种方式使用插件。

复制代码
webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); //经过 npm 安装
const webpack = require('webpack'); //访问内置的插件
const path = require('path');

const config = {
  entry: './path/to/my/entry/file.js',
  output: {
    filename: 'my-first-webpack.bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: 'babel-loader'
      }
    ]
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

module.exports = config;
复制代码

5.一、HTML Webpack Plugin(建立HTML插件)

该个插件的做用是用来自动生成html页面,既能够生成单个页面又能够生成多个页面,而且在生成前能够给它一些的配置参数,它会按照你想要的生成方式去生成页面。

第一步:安装

npm i html-webpack-plugin -D

第二步:在webpack.config.js里引入模块

const HtmlWebpackPlugin=require('html-webpack-plugin');

第三步:在webpack.config.js中的plugins对象里new一个实例

plugins:[
  new HtmlWebpackPlugin({参数})
]

结果

复制代码
const HtmlWebpackPlugin = require('html-webpack-plugin')
 
module.exports = {
  entry: 'index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'index_bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin()
  ]
}
复制代码

参数:

title

生成页面的titile元素

filename

生成的html文件的文件名。默认index.html,能够直接配置带有子目录

复制代码
//webpack.config.js
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    filename: 'index1.html'//可带子目录'html/index1.html'
  })
]
复制代码

template

模版文件路径

templateParameters

{Boolean|Object|Function} 容许覆盖模板中使用的参数

复制代码
//webpack.config.js
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    templateParameters: {
      title: 'xxxx',
      favicon: './favicon/index.ico',
    }
  })
]
复制代码

inject

插入的script插入的位置,四个可选值:
true: 默认值,script标签位于html文件的body底部
body: 同true
headscript标签位于html文件的head标签内
false: 不插入生成的js文件,只是生成的html文件

favicon

为生成的html文件生成一个favicon,属性值是路径

minify

html文件进行压缩。属性值是false或者压缩选项值。默认false不对html文件进行压缩。
html-webpack-plugin中集成的html-minifier,生成模板文件压缩配置,有不少配置项,这些配置项就是minify的压缩选项值。

hash

给生成的js文件尾部添加一个hash值。这个hash值是本次webpack编译的hash值。默认false;

复制代码
//webpack.config.js
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    hash: true
  })
]
//html
<script type="text/javascript" src="bundle.js?59a5ed17040d94df87fe">
//59a5ed17040d94df87fe是本次webpack编译的hash值
复制代码

cache

Boolean类型。只在文件被修改的时候才生成一个新文件。默认值true

showErrors

Boolean类型。错误信息是否写入html文件。默认true

chunks

html文件中引用哪些js文件,用于多入口文件时。不指定chunks时,全部文件都引用

复制代码
//webpack.config.js
entry: {
  index1: path.resolve(__dirname, './index1.js'),
  index2: path.resolve(__dirname, './index2.js'),
  index3: path.resolve(__dirname, './index3.js')
}
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    chunks: [index1, index2]//html文件中只引入index1.js, index2.js
  })
]
复制代码

 

excludeChunks

与chunks相反,html文件不引用哪些js文件

复制代码
//webpack.config.js
entry: {
  index1: path.resolve(__dirname, './index1.js'),
  index2: path.resolve(__dirname, './index2.js'),
  index3: path.resolve(__dirname, './index3.js')
}
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    excludeChunks: [index3.js]//html文件中不引入index3.js
  })
]
复制代码

 

chunksSortMode

控制script标签的引用顺序。默认五个选项:
none: 无序
auto: 默认值, 按插件内置的排序方式
dependency: 根据不一样文件的依赖关系排序
manual: chunks按引入的顺序排序, 即属性chunks的顺序
{Function}: 指定具体的排序规则

xhtml

Boolean类型,默认falsetrue时以兼容xhtml的模式引用文件

示例:

复制代码
plugins:[
    new HtmlWebpackPlugin({
        title:'Hello app',    /*这个值对应html里的title*/
        template:'./src/template.html', //模板文件地址
        filename:'test1.html',  //文件名,默认为index.html(路径相对于output.path的值)
        inject:true,    //script标签的位置,true/body为在</body>标签前,head为在<head>里,false表示页面不引入js文件
        hash:true,  //是否为引入的js文件添加hash值
        chunks:['one'], //页面里要引入的js文件,值对应的是entry里的key。省略参数会把entry里全部文件都引入
        //excludeChunks:['one'],//页面里不能引入的js文件,与chunks恰好相反
        minify:{    //html-webpack-plugin内部集成了html-minifier
            collapseWhitespace:true,    //压缩空格
            removeAttributeQuotes:true, //移除引号
            removeComments:true,        //移除注释
        },
    }),
    //生成两个文件,分别引入两个js文件(如今是一个文件里引入了两个js)
    new HtmlWebpackPlugin({
        title:'kaivon',
        template:'./src/template.html',
        hash:true,
        filename:'test2.html',
        chunks:['two']
    })
]
复制代码

示例1:

webpack.config03.js配置文件

复制代码
//webpack配置文件

//导入用于生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin");

//依赖node中的path模块
var path=require('path');

//定义一个默认模块对象
module.exports={
    entry:{app01:"./src/app03.js"},
    //设置输出结果
    output: {
        //路径,将相对路径转绝对路径
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模块名称,占位
        filename: "[hash:8].bundle.js"
    },
    module: {
    },
    plugins: [
        //建立一个插件对象,并指定参数
        new HtmlWebpackPlugin({
            //指定生成的文件路径与名称
            filename:"../app03.html",
            //标题
            title:"Hello App03!"
        })
    ]
};
复制代码

arc/app03.js

alert("Hello App03!");

打包结果:

运行:

示例2:

webpack.config03.js配置文件

复制代码
//webpack配置文件

//导入用于生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin");

//依赖node中的path模块
var path=require('path');

//定义一个默认模块对象
module.exports={
    entry:{app01:"./src/app03.js"},
    //设置输出结果
    output: {
        //路径,将相对路径转绝对路径
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模块名称,占位
        filename: "[hash:8].bundle.js"
    },
    module: {
    },
    plugins: [
        //建立一个插件对象,并指定参数
        new HtmlWebpackPlugin({
            //指定生成的文件路径与名称
            filename:"../app03.html",
            //标题
            title:"Hello App03!",
            //指定模板
            template:"./templates/tmpl03.html",
            //模板参数,容许覆盖templates中的参数
            templateParameters:{
                content:"Hello templateParameters!",
                //重写title
                title:"Hello App03 title!",
                key:"value"
            },
            minify:{
                removeComments:true,  //移除注释
                collapseWhitespace:true,  //折叠空格
                //更新请参数https://github.com/kangax/html-minifier#options-quick-reference
            }
        })
    ]
};
复制代码

/templates/tmpl03.html 模板文件

  View Code

生成结果:

5.二、Mini-css-extract-plugin(单独提取CSS插件)

将CSS提取为独立的文件的插件,对每一个包含css的js文件都会建立一个CSS文件,支持按需加载css和sourceMap

默认状况下css是被js注入的一段style,以下所示:

只能用在webpack4中,对比另外一个插件 extract-text-webpack-plugin特色:

  • 异步加载
  • 不重复编译,性能更好
  • 更容易使用
  • 只针对CSS

目前缺失功能,HMR(热模块替换)。

  HMR解释

安装:

npm install --save-dev mini-css-extract-plugin

使用:

复制代码
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // 相似 webpackOptions.output里面的配置 能够忽略
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              // 这里能够指定一个 publicPath
              // 默认使用 webpackOptions.output中的publicPath
              publicPath: '../'
            },
          },
          'css-loader',
        ],
      }
    ]
  }
}
复制代码

高级配置:

这个插件应该只用在 production 配置中,而且在loaders链中不使用 style-loader, 特别是在开发中使用HMR,由于这个插件暂时不支持HMR

复制代码
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const devMode = process.env.NODE_ENV !== 'production';

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: devMode ? '[name].css' : '[name].[hash].css',
      chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
    })
  ],
  module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader',
        ],
      }
    ]
  }
}
复制代码

示例:

webpack.config03.js

复制代码
//webpack配置文件

//导入用于生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin");
//导入用于提取css的插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

//依赖node中的path模块
var path=require('path');

//定义一个默认模块对象
module.exports={
    entry:{app01:"./src/app03.js"},
    //设置输出结果
    output: {
        //路径,将相对路径转绝对路径
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模块名称,占位
        filename: "[hash:8].bundle.js"
    },
    module: {
        rules: [
            {
                test: /\.scss$/,
                use: [{
                    loader:MiniCssExtractPlugin.loader //提取css并link
                }, {
                    loader: "css-loader" // 将 CSS 转化成 CommonJS 模块
                }, {
                    loader: "sass-loader" // 将 Scss 编译成 CSS
                }]
            }
        ]
    },
    plugins: [
        //建立一个插件对象,并指定参数
        new HtmlWebpackPlugin({
            //指定生成的文件路径与名称
            filename:"../app03.html",
            //标题
            title:"Hello App03!",
            //指定模板
            template:"./templates/tmpl03.html",
            //模板参数,容许覆盖templates中的参数
            templateParameters:{
                content:"Hello templateParameters!",
                //重写title
                title:"Hello App03 title!",
                key:"value"
            },
            minify:{
                removeComments:true,  //移除注释
                collapseWhitespace:true,  //折叠空格
                //更新请参数https://github.com/kangax/html-minifier#options-quick-reference
            }
        }),
        //建立一个用于提取css的插件对象
        new MiniCssExtractPlugin({
            filename:"[name]_[hash:10].css",
            chunkFilename:"[id]"
        })
    ]
};
复制代码

src/app03.js

import '../css/baseScss.scss';

alert("Hello App03!");

打包生成的结果

复制代码
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <title>Hello App03 title!</title>
    <link href="dist/app01_1b7c11aa92.css" rel="stylesheet">
</head>
<body><h2>Hello templateParameters!</h2>
<script type="text/javascript" src="dist/1b7c11aa.bundle.js"></script>
</body>
</html>
复制代码

运行结果:

5.三、clean-webpack-plugin(删除或清理构建目录)

在用HtmlWebpackPlugin的时候时须要把dist目录删掉再去看生成的文件,clean-webpack-plugin这个插件就能够作这件事情

第一步:安装

npm i clean-webpack-plugin --save-dev

 

第二步:在webpack.config.js里引入模块

const CleanWebpackPlugin=require('clean-webpack-plugin');

 

第三步:在plugins的最前面建立清理对象

复制代码
plugins:[
new CleanWebpackPlugin(['./dist']), //这个必定要放在最上面,做用是先删除dist目录再建立新的dist目录。里面的参数为要删除的目录,放在一个数组里面
...
]
复制代码

 

在文件夹里打开dist所在的目录,并在终端里再次执行命令webpack后,会看到dist目录先被删除后又被建立。

关于clean-webpack-plugin插件的全部配置参数请参考:https://www.npmjs.com/package/clean-webpack-plugin

示例:

复制代码
const CleanWebpackPlugin = require('clean-webpack-plugin'); //installed via npm
const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
const path = require('path');
 
// the path(s) that should be cleaned
let pathsToClean = [
  'dist',
  'build'
]
 
// the clean options to use
let cleanOptions = {
  root:     '/full/webpack/root/path',
  exclude:  ['shared.js'],
  verbose:  true,
  dry:      false
}
 
// sample WebPack config
const webpackConfig = {
  entry: './path/to/my/entry/file.js',
  output: {
    filename: 'my-first-webpack.bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        loader: 'babel-loader'
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(pathsToClean, cleanOptions),
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
}
复制代码

6、DevServer开发服务器 

在实际开发中咱们可能会须要完成以下功能:

  1. 提供 HTTP 服务而不是使用本地文件预览;
  2. 监听文件的变化并自动刷新网页,作到实时预览;
  3. 支持 Source Map,以方便调试。

Webpack 原生支持上述第二、3点内容,再结合官方提供的开发工具 DevServer 也能够很方便地作到第1点。 DevServer 会启动一个 HTTP 服务器用于服务网页请求,同时会帮助启动 Webpack ,并接收 Webpack 发出的文件更变信号,经过 WebSocket 协议自动刷新网页作到实时预览。

6.一、快速开启DevServer

安装 DevServer:

npm i -D webpack-dev-server

安装成功后在项目的根目录下执行webpack-dev-server 命令, DevServer 服务器就启动了,这时你会看到控制台有一串日志输出:

Project is running at http://localhost:8080/

webpack output is served from /

如今就能够直接访问了

这意味着 DevServer 启动的 HTTP 服务器监听在 http://localhost:8080/ ,DevServer 启动后会一直驻留在后台保持运行,访问这个网址你就能获取项目根目录下的 index.html。 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

0分钟学会前端工程化(webpack4.0)

 

1、概要

1.一、前端工程化

随着前端的不断发展与壮大,前端变得愈来愈复杂,组件化、模块化、工程化、自动化成了前端发展中不可或缺的一部分,具体到前端工程化,面临的问题是如何提升编码->测试->维护阶段的生产效率。

前端工程化是使用软件工程的技术和方法来进行前端项目的开发、维护和管理。

前端工程化是依据业务特色,将前端开发的规范、流程、技术、工具、经验等造成规范并创建成一种标准的体系。

如今的项目可能会不停的迭代,发布就成了平常开发的一部分,前端不只要保证功能还要保证性能,传统的一次次的发布效率会很是低,前端工程化通常都有会借助一些工具。

实现前端工程化的目的简单来讲就是经过流程规范、自动化工具来提高前端的开发效率、性能、质量、多人协做能力以及开发体验,创建前端工程化是各个团队必经的成长过程。

1.1.一、前端工程化的任务

前端不只要保证功能还要考虑性能,要减小http请求数量、压缩、合并、预处理、规范代码、清理、打包、转换等工做。

前端大部分状况下源代码没法直接运行,必须经过转换后才能够正常运行。构建就是作这件事情,把源代码转换成发布到线上的可执行 JavaScrip、CSS、HTML 代码,包括以下内容。

(1)、代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等。

(2)、文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片等。

(3)、代码分割:提取多个页面的公共代码、提取首屏不须要执行部分的代码让其异步加载。

(4)、模块合并:在采用模块化的项目里会有不少个模块和文件,须要构建功能把模块分类合并成一个文件。

(5)、自动刷新:监听本地源代码的变化,自动从新构建、刷新浏览器。

(6)、代码校验:在代码被提交到仓库前须要校验代码是否符合规范,以及单元测试是否经过。

(7)、自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统。

构建实际上是工程化、自动化思想在前端开发中的体现,把一系列流程用代码去实现,让代码自动化地执行这一系列复杂的流程。 构建给前端开发注入了更大的活力,解放了咱们的生产力。

1.二、前端工程化工具

历史上前后出现一系列构建工具,它们各有其优缺点。因为前端工程师很熟悉 JavaScript ,Node.js 又能够胜任全部构建需求,因此大多数构建工具都是用 Node.js 开发的。

构建工具的主要功能就是实现自动化处理,例如对代码进行检查、预编译、合并、压缩;生成雪碧图、sourceMap、版本管理;运行单元测试、监控等,固然有的工具还提供模块化、组件化的开发流程功能。

 

若是把工具按类型分能够分为这三类:

(一)、基于任务运行的工具:Grunt、Gulp

它们会自动执行指定的任务,就像流水线,把资源放上去而后经过不一样插件进行加工,它们包含活跃的社区,丰富的插件,能方便的打造各类工做流。

(二)、基于模块化打包的工具:Browserify、Webpack、rollup.js

有过 Node.js 开发经历的应该对模块很熟悉,须要引用组件直接一个 require 就 OK,这类工具就是这个模式,还能够实现按需加载、异步加载模块。

(三)、整合型工具:Yeoman、FIS、jdf、Athena、cooking、weflow

使用了多种技术栈实现的脚手架工具,好处是即开即用,缺点就是它们约束了技术选型,而且学习成本相对较高。

1.2.一、Grunt

Grunt([ɡrʌnt]做呼噜声) 生态系统很是庞大,而且一直在增加。因为拥有数量庞大的插件可供选择,所以,你能够利用 Grunt 自动完成许多事,而且花费不多的代价。若是找不到你所须要的插件,那就本身动手创造一个 Grunt 插件,而后将其发布到 npm 上吧。

官网:https://gruntjs.com/

GitHub:https://github.com/gruntjs/

中文网:https://www.gruntjs.net/

对于须要反复重复的任务,例如压缩(minification)、编译、单元测试、linting等,自动化工具能够减轻你的劳动,简化你的工做。当你在 Gruntfile 文件正确配置好了任务,任务运行器就会自动帮你或你的小组完成大部分无聊的工做。

Grunt 是老牌的构建工具,特色是配置驱动,你须要作的就是了解各类插件的功能,而后把配置整合到 Gruntfile.js 中,下面是配置例子:

复制代码
module.exports = function(grunt) {
    grunt.initConfig({
        jshint: {
            files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
            options: {
                globals: {
                    jQuery: true
                }
            }
        },
        watch: {
            files: ['<%= jshint.files %>'],
            tasks: ['jshint']
        }
    });

    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.registerTask('default', ['jshint']);
};
复制代码

Grunt 缺点也是配置驱动,当任务很是多的状况下,试图用配置完成全部事简直就是个灾难;再就是它的 I/O 操做也是个弊病,它的每一次任务都须要从磁盘中读取文件,处理完后再写入到磁盘,例如:我想对多个 less 进行预编译、压缩操做,那么 Grunt 的操做就是:

读取 less 文件 -> 编译成 css -> 存储到磁盘 -> 读取 css -> 压缩处理 -> 存储到磁盘

这样一来当资源文件较多,任务较复杂的时候性能就是个问题了。

1.2.二、Gulp

Gulp(ɡʌlp狼吞虎咽地吃,吞咽)是一个基于流的自动化构建工具。 除了能够管理和执行任务,还支持监听文件、读写文件。

中文网:https://www.gulpjs.com.cn/

官网:https://gulpjs.com/

特色:

易于使用:经过代码优于配置的策略,Gulp 让简单的任务简单,复杂的任务可管理。

构建快速:利用 Node.js 流的威力,你能够快速构建项目并减小频繁的 IO 操做。

插件高质:Gulp 严格的插件指南确保插件如你指望的那样简洁高质得工做。

易于学习:经过最少的 API,掌握 Gulp 不太费力,构建工做尽在掌握:如同一系列流管道。

Gulp 被设计得很是简单,只经过下面5种个方法就能够胜任几乎全部构建场景:

经过 gulp.task 注册一个任务;

经过 gulp.run 执行任务;

经过 gulp.watch 监听文件变化;

经过 gulp.src 读取文件;

经过 gulp.dest 写文件。

Gulp 的最大特色是引入了流的概念,同时提供了一系列经常使用的插件去处理流,流能够在插件之间传递

Gulp 特色是代码驱动,写任务就和写普通的 Node.js 代码同样:

复制代码
var gulp = require('gulp');
var pug = require('gulp-pug');
var less = require('gulp-less');
var minifyCSS = require('gulp-csso');

gulp.task('html', function(){
    return gulp.src('client/templates/*.pug')
        .pipe(pug())
        .pipe(gulp.dest('build/html'))
});

gulp.task('css', function(){
    return gulp.src('client/templates/*.less')
        .pipe(less())
        .pipe(minifyCSS())
        .pipe(gulp.dest('build/css'))
});

gulp.task('default', [ 'html', 'css' ]);
复制代码

再一个对文件读取是流式操做(Stream),也就是说一次 I/O 能够处理多个任务,仍是 less 的例子,Gulp 的流程就是:

读取 less 文件 -> 编译成 css -> 压缩处理 -> 存储到磁盘

Gulp 做为任务类型的工具没有明显的缺点,惟一的问题可能就是完成相同的任务它须要写的代码更多一些,因此除非是项目有历史包袱(原有项目就是基于 Grunt 构建)在 Grunt 与 Gulp 对比看来仍是比较推荐 Gulp!

适用场景:

经过上面的介绍能够看出它们侧重对整个过程的控制管理,实现简单、对架构无要求、不改变开发模式,因此很是适合前端、小型、须要快速启动的项目。

1.2.三、Yeoman

Yeoman([ˈjoʊmən]自耕农,自由民; 义勇骑兵队成员,young+man)的目的不只是要为新项目创建工做流,同时仍是为了解决前端开发所面临的诸多严重问题,例如零散的依赖关系。
Yeoman是Google的团队和外部贡献者团队合做开发的,他的目标是经过Grunt(一个用于开发任务自动化的命令行工具)和Bower(一个HTML、CSS、Javascript和图片等前端资源的包管理器)的包装为开发者建立一个易用的工做流。

Yeoman是一个强健的脚手架与构建工具,库,及工做流程的组合,帮你网页开发者快速建立出漂亮并且引人入胜的网页程序,Yeoman帮助咱们建立项目,提供更好的工具来使咱们的项目更多样化。

Yeoman提供generator系统,一个generator是一个插件,在咱们在一个完整的项目上使用‘yo’命令时,会运行该generator。经过这些官方的Generators,推出了Yeoman工做流,工做流是一个健壮、有本身特点的客户端堆栈,包含能快速构建漂亮的网络应用的工具和框架。Yeoman提供了负责开始项目开发的一切,没有任何让人头痛的手动配置。

Yeoman主要提供了三个工具:脚手架(yo),构建工具(grunt),包管理器(bower)。这三个工具是分别独立开发的,可是须要配合使用,来实现咱们更高效的工做流模式。

小结:

在 Npm Script 和 Grunt 时代,Web 开发要作的事情变多,流程复杂,自动化思想被引入,用于简化流程;

在 Gulp 时代开始出现一些新语言用于提升开发效率,流式处理思想的出现是为了简化文件转换的流程,例如将 ES6 转换成 ES5。

在 Webpack 时代因为单页应用的流行,一个网页的功能和实现代码变得庞大,Web 开发向模块化改进。

这些构建工具都有各自的定位和专一点,它们之间既能够单独地完成任务,也能够相互搭配起来弥补各自的不足。 在了解这些常见的构建工具后,你须要根据本身的需求去判断应该如何选择和搭配它们才能更好地完成本身的需求。

通过多年的发展, Webpack 已经成为构建工具中的首选,缘由是:

大多数团队在开发新项目时会采用紧跟时代的技术,这些技术几乎都会采用“模块化+新语言+新框架”,Webpack 能够为这些新项目提供一站式的解决方案;

Webpack 有良好的生态链和维护团队,能提供良好的开发体验和保证质量;

Webpack 被全世界的大量 Web 开发者使用和验证,能找到各个层面所需的教程和经验分享。

1.三、WebPack

webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序须要的每一个模块,而后将全部这些模块打包成一个或多个 bundle。

Webpack 是一个打包模块化 JavaScript 的工具,在 Webpack 里一切文件皆模块,经过 Loader 转换文件,经过 Plugin 注入钩子,最后输出由多个模块组合成的文件。Webpack 专一于构建模块化项目。

其官网的首页图很形象的画出了 Webpack 是什么,以下:

一切文件:JavaScript、CSS、SCSS、图片、模板,在 Webpack 眼中都是一个个模块,这样的好处是能清晰的描述出各个模块之间的依赖关系,以方便 Webpack 对模块进行组合和打包。 通过 Webpack 的处理,最终会输出浏览器能使用的静态资源。

Webpack 具备很大的灵活性,能配置如何处理文件,大体使用以下:

复制代码
module.exports = {
// 全部模块的入口,Webpack 从入口开始递归解析出全部依赖的模块
    entry: './app.js',
    output: {
// 把入口所依赖的全部模块打包成一个文件 bundle.js 输出 
        filename: 'bundle.js'
    }
}
复制代码

1.3.一、Webpack的特色

把一切都视为模块:无论是 CSS、JS、Image 仍是 HTML 均可以互相引用,经过定义 entry.js,对全部依赖的文件进行跟踪,将各个模块经过 loader 和 plugins 处理,而后打包在一块儿。

按需加载:打包过程当中 Webpack 经过 Code Splitting 功能将文件分为多个 chunks,还能够将重复的部分单独提取出来做为 commonChunk,从而实现按需加载。

优势:

专一于处理模块化的项目,能作到开箱即用一步到位;

经过 Plugin 扩展,完整好用又不失灵活;

使用场景不只限于 Web 开发;

社区庞大活跃,常常引入紧跟时代发展的新特性,能为大多数场景找到已有的开源扩展;

良好的开发体验。

缺点:

Webpack的缺点是只能用于采用模块化开发的项目。

上手比较难、对于新手而言须要经历踩坑的过程。

对于Server 端渲染的多页应用有点力不从心。

小结:

Webpack 特别适合配合 React.js、Vue.js 构建单页面应用以及须要多人合做的大型项目,在规范流程都已约定好的状况下每每能极大的提高开发效率与开发体验。

1.3.二、资源

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

github:https://github.com/webpack/webpack

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

深刻浅出webpack电子书:http://webpack.wuhaolin.cn/

1.3.三、工做流程

Webpack 是经过配置来实现管理,与 Grunt 不一样的是它包含的许多自动化的黑盒操做因此配置起来会简单不少(但遇到问题调试起来就很麻烦),一个典型的配置以下:

复制代码
module.exports = {
    //插件项
    plugins: [commonsPlugin],
    //页面入口文件配置
    entry: {
        index : './src/js/page/index.js'
    },
    //入口文件输出配置
    output: {
        path: 'dist/js/page',
        filename: '[name].js'
    },
    module: {
        //加载器配置
        loaders: [
            { test: /\.css$/, loader: 'style-loader!css-loader' },
            { test: /\.js$/, loader: 'jsx-loader?harmony' },
            { test: /\.scss$/, loader: 'style!css!sass?sourceMap'},
            { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}
        ]
    },
    //其它解决方案配置
    resolve: {
        root: '/Users/Bell/github/flux-example/src', //绝对路径
        extensions: ['', '.js', '.json', '.scss'],
        alias: {
            AppStore : 'js/stores/AppStores.js',
            ActionType : 'js/actions/ActionType.js',
            AppAction : 'js/actions/AppAction.js'
        }
    }
};
复制代码

 

1.3.四、搭建WebPack开发环境

(1)、安装NodeJS

在用 Webpack 执行构建任务时须要经过 webpack 可执行文件去启动构建任务,因此须要安装 webpack 可执行文件。 在安装 Webpack 前请确保你的系统安装了5.0.0及以上版本的 Node.js。

https://nodejs.org/下载安装

设置国内npm的镜像

$ npm install -g cnpm --registry=https://registry.npm.taobao.org

使用时用cnpm代替npm

(2)、安装webpack

安装 Webpack 到全局

安装到全局后你能够在任何地方共用一个 Webpack 可执行文件,而不用各个项目重复安装,安装方式以下:

npm i -g webpack

cli:

全部cli参数:

  View Code

要安装 Webpack 到本项目,可按照你的须要选择如下任意命令运行:

复制代码
# npm i -D 是 npm install --save-dev 的简写,是指安装模块并保存到 package.json 的 devDependencies
# 安装最新稳定版
npm i -D webpack

# 安装指定版本
npm i -D webpack@<version>

# 安装最新体验版本
npm i -D webpack@beta
复制代码

2、快速上手

2.一、建立一个项目或目录

建立一个空项目或一个空目录,不必定须要使用IDE,这里我使用WebStorm

2.二、初始化项目

npm init -y (-y直接跳过提问阶段)

复制代码
name - 包名.
version - 包的版本号。
description - 包的描述。
homepage - 包的官网URL。
author - 包的做者,它的值是你在https://npmjs.org网站的有效帐户名,遵循“帐户名<邮件>”的规则,例如:zhangsan <zhangsan@163.com>。
contributors - 包的其余贡献者。
dependencies / devDependencies - 生产/开发环境依赖包列表。它们将会被安装在 node_module 目录下。
repository - 包代码的Repo信息,包括type和URL,type能够是git或svn,URL则是包的Repo地址。
main - main 字段指定了程序的主入口文件,require('moduleName') 就会加载这个文件。这个字段的默认值是模块根目录下面的 index.js。
keywords - 关键字
复制代码

package.json详解

2.三、安装webpack

webpack4须要安装webpack-cli:

npm i webpack webpack-cli --save-dev

2.四、建立目录与文件

src/bar.js

复制代码
//定义模块
//部分依赖lodash中的join方法
import {join} from 'lodash'

//导出一个默认模块
export default function bar() {
    function component() {
        //建立DOM元素
        var element=document.createElement("h2");
        //使用join链接数组将结果写入元素的html中
        element.innerHTML=join(['Hello','Webpack','!'],' ');
        return element;
    }
    //在body中添加子元素
    document.body.appendChild(component());
}
复制代码

实现使用lodash的join 链接字符串,在网页中输出字符串

依赖lodash、npm安装lodash,在bar.js中import lodash的join方法,输出text

npm i lodash --save

src/index.js

复制代码
//入口文件

//导入自定义好的模块
import bar from './bar';
//调用
bar();
复制代码

建立配置文件webpack.config.js

复制代码
//webpack配置文件

//依赖node中的path模块
const path=require('path');

//定义一个默认模块对象
module.exports={
    //指定入口文件的位置
    entry:"./src/index.js",
    //设置输出结果
    output: {
        //路径,将相对路径转绝对路径
        path:path.resolve(__dirname,'dist'),
        //文件
        filename: "bundle.js"
    }
};
复制代码

path.resolve获取文件的路径,_dirname为当前模块的绝对路径,详细解释以下:

  View Code

index.html

webpack建立dist文件在dist中生成打包文件,而后再index.html中引用index.js文件

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello WebPack</title>
</head>
<body>
<h2>Hello WebPack</h2>
<script src="dist/bundle.js"></script>
</body>
</html>
复制代码

2.五、使用webpack命令打包

能够指定配置文件

webpack --config webpack.config.js

也可使用默认的配置文件

webpack

打包的结果:

  View Code

 bundle.js文件:

2.六、运行

3、核心概念与执行过程

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序须要的每一个模块,而后将全部这些模块打包成一个或多个 bundle。

从 webpack v4.0.0 开始,能够不用引入一个配置文件。然而,webpack 仍然仍是高度可配置的。在开始前你须要先理解几个核心概念:

3.一、模块(Module)

在Webpack里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的Entry开始递归找出全部依赖的模块。

webpack把一切都视为模块,无论是 CSS、JS、Image 仍是 HTML 均可以互相引用。Node.js 从最一开始就支持模块化编程。然而,在 web,模块化的支持正缓慢到来。在 web 存在多种支持 JavaScript 模块化的工具,这些工具各有优点和限制。webpack 基于从这些系统得到的经验教训,并将模块的概念应用于项目中的任何文件。

什么是 webpack 模块

对比 Node.js 模块,webpack 模块可以以各类方式表达它们的依赖关系,几个例子以下:

  1. ES2015 import 语句
  2. CommonJS require() 语句
  3. AMD define 和 require 语句
  4. css/sass/less 文件中的 @import 语句。
  5. 样式(url(...))或 HTML 文件(<img src=...>)中的图片连接(image url)

支持的模块类型

webpack 经过 loader 能够支持各类语言和预处理器编写模块。loader 描述了 webpack 如何处理 非 JavaScript(non-JavaScript) _模块_,而且在 bundle 中引入这些依赖。 webpack 社区已经为各类流行语言和语言处理器构建了 loader,包括:

  1. CoffeeScript
  2. TypeScript
  3. ESNext (Babel)
  4. Sass
  5. Less
  6. Stylus

3.二、入口(entry)

入口,Webpack 执行构建的第一步将从 Entry 开始,可抽象成输入。

入口起点(entry point)指示 webpack 应该使用哪一个模块,来做为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。

每一个依赖项随即被处理,最后输出到称之为 bundles 的文件中,咱们将在下一章节详细讨论这个过程。

能够经过在 webpack 配置中配置 entry 属性,来指定一个入口起点(或多个入口起点)。默认值为 ./src。

接下来咱们看一个 entry 配置的最简单例子:

复制代码
webpack.config.js

module.exports = {
    entry: './path/to/my/entry/file.js'
};
复制代码

根据应用程序的特定需求,能够以多种方式配置 entry 属性。

多入口与多出口:

复制代码
{
  entry: {
    app: './src/app.js',
    search: './src/search.js'
  },
  output: {
    filename: '[name].js',
    path: __dirname + '/dist'
  }
}

// 写入到硬盘:./dist/app.js, ./dist/search.js
复制代码

经常使用的占位:

  1. [hash]:模块标识符(module identifier)的 hash
  2. [chunkhash]:chunk 内容的 hash
  3. [name]:模块名称,key的名称,非文件名称
  4. [id]:模块标识符(module identifier)
  5. [query]:模块的 query,例如,文件名 ? 后面的字符串

3.三、出口(output)

输出结果,在 Webpack 通过一系列处理并得出最终想要的代码后输出结果。

output 属性告诉 webpack 在哪里输出它所建立的 bundles,以及如何命名这些文件,默认值为 ./dist。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。你能够经过在配置中指定一个 output 字段,来配置这些处理过程:

复制代码
webpack.config.js

const path = require('path');

module.exports = {
    entry: './path/to/my/entry/file.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'my-first-webpack.bundle.js'
    }
};
复制代码

在上面的示例中,咱们经过 output.filename 和 output.path 属性,来告诉 webpack bundle 的名称,以及咱们想要 bundle 生成(emit)到哪里。可能你想要了解在代码最上面导入的 path 模块是什么,它是一个 Node.js 核心模块,用于操做文件路径。

示例:

3.四、模块转换器(loader)

模块转换器,用于把模块原内容按照需求转换成新内容。

loader 让 webpack 可以去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 能够将全部类型的文件转换为 webpack 可以处理的有效模块,而后你就能够利用 webpack 的打包能力,对它们进行处理。

本质上,webpack loader 将全部类型的文件,转换为应用程序的依赖图(和最终的 bundle)能够直接引用的模块。

注意,loader 可以 import 导入任何类型的模块(例如 .css 文件),这是 webpack 特有的功能,其余打包程序或任务执行器的可能并不支持。咱们认为这种语言扩展是有很必要的,由于这可使开发人员建立出更准确的依赖关系图。

在更高层面,在 webpack 的配置中 loader 有两个目标:

  1. test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。
  2. use 属性,表示进行转换时,应该使用哪一个 loader。
复制代码
webpack.config.js

const path = require('path');

const config = {
    output: {
        filename: 'my-first-webpack.bundle.js'
    },
    module: {
        rules: [
            { test: /\.txt$/, use: 'raw-loader' }
        ]
    }
};

module.exports = config;
复制代码

以上配置中,对一个单独的 module 对象定义了 rules 属性,里面包含两个必须属性:test 和 use。这告诉 webpack 编译器(compiler) 以下信息:

“webpack 编译器,当你碰到「在 require()/import 语句中被解析为 '.txt' 的路径」时,在你对它打包以前,先使用 raw-loader 转换一下。”

3.五、插件(plugins)

扩展插件,在 Webpack 构建流程中的特定时机注入扩展逻辑来改变构建结果或作你想要的事情。

loader 被用于转换某些类型的模块,而插件则能够用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到从新定义环境中的变量。插件接口功能极其强大,能够用来处理各类各样的任务。

想要使用一个插件,你只须要 require() 它,而后把它添加到 plugins 数组中。多数插件能够经过选项(option)自定义。你也能够在一个配置文件中由于不一样目的而屡次使用同一个插件,这时须要经过使用 new 操做符来建立它的一个实例。

复制代码
webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); // 经过 npm 安装
const webpack = require('webpack'); // 用于访问内置插件

const config = {
    module: {
        rules: [
            { test: /\.txt$/, use: 'raw-loader' }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({template: './src/index.html'})
    ]
};

module.exports = config;
复制代码

3.六、模式(mode)

经过选择 development 或 production 之中的一个,来设置 mode 参数,你能够启用相应模式下的 webpack 内置的优化

module.exports = {
    mode: 'production'
};

webpack4容许咱们指定编译使用开发模式仍是生产模式,这由mode这个配置来控制,value为枚举值:development/production,分别对应开发模式和生产模式(这个配置能够做为命令行的配置参数也能够做为配置文件中的一个配置项,默认值是production,即生产模式)。

源码仍是不支持调试(都用eval函数包住),指定编译时的source-map生成方式,默认值是eval,能够解决问题。

3.七、代码块(Chunk)

一个 Chunk 由多个模块组合而成,用于代码合并与分割。

3.八、WebPack执行过程

Webpack 启动后会从 Entry 里配置的 Module 开始递归解析 Entry 依赖的全部 Module。 每找到一个 Module, 就会根据配置的 Loader 去找出对应的转换规则,对 Module 进行转换后,再解析出当前 Module 依赖的 Module。 这些模块会以 Entry 为单位进行分组,一个 Entry 和其全部依赖的 Module 被分到一个组也就是一个 Chunk。最后 Webpack 会把全部 Chunk 转换成文件输出。 在整个流程中 Webpack 会在恰当的时机执行 Plugin 里定义的逻辑。

Webpack从入口(entry)开始工做,一般这些是JavaScript模块,其中webpack开始其遍历过程。在此过程当中,webpack会根据加载器配置评估入口(entry)匹配,这些配置告诉webpack如何转换每一个匹配。

入口(entry)自己就是一个模块。当webpack遇到一个入口时,webpack会尝试使用入口的resolve配置将入口与文件系统匹配。除了node_modules以外,咱们还能够告诉webpack对特定目录执行查找。也能够调整webpack与文件扩展名匹配的方式,而且能够为目录定义特定的别名。该耗竭与包章涵盖了更详细的这些想法。

若是解析经过失败,webpack会引起运行时错误。若是webpack设法正确解析文件,webpack将根据加载器定义对匹配的文件执行处理。每一个加载器对模块内容应用特定的转换。

能够经过多种方式配置加载程序与已解析文件匹配的方式,包括文件类型和文件系统中的位置。Webpack的灵活性甚至容许咱们根据文件导入项目的位置对文件应用特定的转换。

对webpack的加载器执行相同的解析过程。Webpack容许咱们在肯定应使用哪一个加载器时应用相似的逻辑。因为这个缘由,装载程序已经解析了本身的配置。若是webpack没法执行加载程序查找,则会引起运行时错误。

在实际应用中你可能会遇到各类奇怪复杂的场景,不知道从哪开始。 根据以上总结,你会对 Webpack 有一个总体的认识,这能让你在之后使用 Webpack 的过程当中快速知道应该经过配置什么去完成你想要的功能,而不是无从下手。

 下图能够简易的描述出webpack打包过程,该过程主要分为三个阶段:module构建、trunk构建和产出三个阶段:

4、模块转换器Loader

loader 用于对模块的源代码进行转换。loader 可使你在 import 或"加载"模块时预处理文件。所以,loader 相似于其余构建工具中“任务(task)”,并提供了处理前端构建步骤的强大方法。loader 能够将文件从不一样的语言(如 TypeScript)转换为 JavaScript,或将内联图像转换为 data URL。loader 甚至容许你直接在 JavaScript 模块中 import CSS文件!

loader 是对应用程序中资源文件进行转换。它们是(运行在 Node.js 中的)函数,能够将资源文件做为参数的来源,而后返回新的资源文件。

 

4.一、loader特性

loader 支持链式传递。可以对资源使用流水线(pipeline)。一组链式的 loader 将按照相反的顺序执行。loader 链中的第一个 loader 返回值给下一个 loader。在最后一个 loader,返回 webpack 所预期的 JavaScript。

  • loader 能够是同步的,也能够是异步的。
  • loader 运行在 Node.js 中,而且可以执行任何可能的操做。
  • loader 接收查询参数。用于对 loader 传递配置。
  • loader 也可以使用 options 对象进行配置。

除了使用 package.json 常见的 main 属性,还能够将普通的 npm 模块导出为 loader,作法是在 package.json 里定义一个 loader 字段。

插件(plugin)能够为 loader 带来更多特性。

loader 可以产生额外的任意文件。

loader 经过(loader)预处理函数,为 JavaScript 生态系统提供了更多能力。 用户如今能够更加灵活地引入细粒度逻辑,例如压缩、打包、语言翻译和其余更多。

loader 遵循标准的模块解析。多数状况下,loader 将从模块路径(一般将模块路径认为是 npm install, node_modules)解析。

loader 模块须要导出为一个函数,而且使用 Node.js 兼容的 JavaScript 编写。一般使用 npm 进行管理,可是也能够将自定义 loader 做为应用程序中的文件。按照约定,loader 一般被命名为 xxx-loader(例如 json-loader)。

4.二、使用loader的三种方式

(1)、配置(推荐):在 webpack.config.js 文件中指定 loader

module.rules 容许你在 webpack 配置中指定多个 loader。 这是展现 loader 的一种简明方式,而且有助于使代码变得简洁。同时让你对各个 loader 有个全局概览:

复制代码
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          { loader: 'style-loader' },
          {
            loader: 'css-loader',
            options: {
              modules: true
            }
          }
        ]
      }
    ]
  }
复制代码

Loaders须要单独安装而且须要在webpack.config.js中的modules关键字下进行配置,Loaders的配置包括如下几方面:

复制代码
test:一个用以匹配loaders所处理文件的拓展名的正则表达式(必须)

loader:loader的名称(必须)

include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不须要处理的文件(文件夹)(可选)

query:为loaders提供额外的设置选项(可选)
复制代码

(2)、内联:在每一个 import 语句中显式指定 loader

能够在 import 语句或任何等效于 "import" 的方式中指定 loader。使用 ! 将资源中的 loader 分开。分开的每一个部分都相对于当前目录解析。

import Styles from 'style-loader!css-loader?modules!./styles.css';

经过前置全部规则及使用 !,能够对应覆盖到配置中的任意 loader。

选项能够传递查询参数,例如 ?key=value&foo=bar,或者一个 JSON 对象,例如 ?{"key":"value","foo":"bar"}。

尽量使用 module.rules,由于这样能够减小源码中的代码量,而且能够在出错时,更快地调试和定位 loader 中的问题。

(3)、CLI:在 shell 命令中指定它们

你也能够经过 CLI 使用 loader:

webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'

这会对 .jade 文件使用 jade-loader,对 .css 文件使用 style-loader 和 css-loader。

4.三、常见的loader

4.3.一、文件

  • raw-loader 加载文件原始内容(utf-8)
  • val-loader 将代码做为模块执行,并将 exports 转为 JS 代码
  • url-loader 像 file loader 同样工做,但若是文件小于限制,能够返回 data URL
  • file-loader 将文件发送到输出文件夹,并返回(相对)URL

4.3.二、JSON

4.3.三、转换编译(Transpiling)

4.3.四、模板(Templating)

  • html-loader 导出 HTML 为字符串,须要引用静态资源
  • pug-loader 加载 Pug 模板并返回一个函数
  • jade-loader 加载 Jade 模板并返回一个函数
  • markdown-loader 将 Markdown 转译为 HTML
  • react-markdown-loader 使用 markdown-parse parser(解析器) 将 Markdown 编译为 React 组件
  • posthtml-loader 使用 PostHTML 加载并转换 HTML 文件
  • handlebars-loader 将 Handlebars 转移为 HTML
  • markup-inline-loader 将内联的 SVG/MathML 文件转换为 HTML。在应用于图标字体,或将 CSS 动画应用于 SVG 时很是有用。

4.3.五、样式

  • style-loader 将模块的导出做为样式添加到 DOM 中
  • css-loader 解析 CSS 文件后,使用 import 加载,而且返回 CSS 代码
  • less-loader 加载和转译 LESS 文件
  • sass-loader 加载和转译 SASS/SCSS 文件
  • postcss-loader 使用 PostCSS 加载和转译 CSS/SSS 文件
  • stylus-loader 加载和转译 Stylus 文件

4.3.六、清理和测试(Linting && Testing)

4.3.七、框架(Frameworks)

  • vue-loader 加载和转译 Vue 组件
  • polymer-loader 使用选择预处理器(preprocessor)处理,而且 require() 相似一等模块(first-class)的 Web 组件
  • angular2-template-loader 加载和转译 Angular 组件

4.四、raw-loader(文件原始内容转换器)

一个能够用于加载文件做为字符串使用的加载器,使用UTF-8编码。

安装

npm i --D raw-loader

 安装结果:

用法一:

经过 webpack 配置、命令行或者内联使用 loader。

复制代码
webpack.config.js

module.exports = {
    module: {
        rules: [
            {
                test: /\.txt$/,
                use: 'raw-loader'
            }
        ]
    }
}
复制代码

在你的项目中

import txt from './file.txt';

用法二:经过命令行(CLI)

webpack --module-bind 'txt=raw-loader'

用法三:在你的项目中

import txt from 'file.txt';

内联使用

import txt from 'raw-loader!./file.txt';

示例:

webpack.config.json

  View Code

src/file1.txt

A loader for webpack that lets you import files as a string.

src/bar.js

复制代码
//定义模块
//部分依赖lodash中的join方法
import {join} from 'lodash';
//导入模块,得到file1.txt中的文件内容,被raw-loader处理
import message from './file1.txt';

//导出一个默认模块
export default function bar() {
    function component() {
        //建立DOM元素
        var element=document.createElement("h2");
        //使用join链接数组将结果写入元素的html中
        element.innerHTML=join(['Hello','Webpack','!'],' ')+"<br/>"+message;
        return element;
    }
    //在body中添加子元素
    document.body.appendChild(component());
}
复制代码

运行结果:

内联使用模块处理器:

4.五、CSS Loader(样式处理)

webpack提供两个工具处理样式表,css-loader 和 style-loader,两者处理的任务不一样,css-loader使你可以使用相似@import 和 url(...)的方法实现 require()的功能,style-loader将全部的计算后的样式加入页面中,两者组合在一块儿使你可以把样式表嵌入webpack打包后的JS文件中。

  • css-loader: 加载.css文件
  • style-loader:使用<style>将css-loader内部样式注入到咱们的HTML页面

css-loader详解:

https://www.npmjs.com/package/css-loader

https://www.webpackjs.com/loaders/css-loader/

style-loader详解:

https://www.npmjs.com/package/style-loader

https://www.webpackjs.com/loaders/style-loader/

4.5.一、安装

//安装
npm i style-loader css-loader -D

4.5.二、配置

复制代码
const path = require("path");

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: "bundle.js"
    },
    module: {
        rules: [
            {
                test:/\.css/,
                use:['style-loader',{
                    loader: 'css-loader',
                    options: {
                        sourceMap:true
                    }
                }]
            }
        ]
    },
    mode: "development"
};
复制代码

4.5.三、定义样式与引用

base.css

复制代码
h2{
    height: 40px;
    line-height: 40px;
    background: crimson;
    color:#fff;
}
复制代码

bar.js

复制代码
import {join} from 'lodash';
import base from '../css/base.css';

export default function bar() {
    function component() {
        var element=document.createElement("h2");
        element.innerHTML=join(['Hello','Webpack!']);
        return element;
    }
    document.body.appendChild(component());
}
复制代码

4.5.四、打包运行

打包:

运行:

生成代码:

4.5.五、注意事项

  1. rules里的数据类型为对象,每个loader都是一个对象
  2. test表示loader要处理什么类型的文件,这里用了一个正则去匹配文件类型
  3. use表示要使用哪一个loader,它的值是个数组,loader的使用顺序是从后往前
  4. 这个loader的意思为,在入口文件里找到.css类型的文件,先拿css-loader去处理成浏览器认识的css,再拿style-loader把处理后的css放在页面的style标签里

4.六、sass-loader(加载和转译 SASS/SCSS 文件)

加载sass或scss文件并转译成css

用css-loader或raw-loader 转换成一个JS模块或用ExtractTextPlugin插件将样式分隔成一个单独文件。

安装

npm i sass-loader node-sass --D

 

node-sass 和 webpack 是 sass-loader 的 peerDependency,所以可以精确控制它们的版本。

示例

css/baseScss.scss

复制代码
$height:50px;
$color:#3366ff;

h2{
  background: $color;
  height: $height;
  line-height: $height;
  color: white;
  padding-left: $height/5;
}
复制代码

 

经过将 style-loader 和 css-loader 与 sass-loader 链式调用,能够马上将样式做用在 DOM 元素。

配置webpack.config.json

复制代码
//webpack配置文件

//依赖node中的path模块
var path=require('path');

//定义一个默认模块对象
module.exports={
    //指定入口文件的位置,多入口
    entry:{
        index:"./src/index.js",
        main:"./src/main.js"
    },
    //设置输出结果
    output: {
        //路径,将相对路径转绝对路径
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模块名称,占位
        filename: "[name].bundle.js"
    },
    module: {  //模块处理
        rules: [ //处理器
            {
                test:/\.txt$/,  //当模块的后缀为.txt时匹配
                use: "raw-loader"  //模块转换器,能够以对象的形式指定参数
            },
            {
                test:/\.css$/,  //匹配全部css模块
                //use表示要使用哪一个loader,它的值是个数组,loader的使用顺序是从后往前
                use: ["style-loader",{
                    loader: "css-loader",  //转换器名称
                    options: {  //配置选项
                        modules:true,  //模块化
                        sourceMap:true  //是否生成调试文件
                    }
                }]  //使用多个模块转换器
            },
            {
                test: /\.scss$/,
                use: [{
                    loader: "style-loader" // 将 JS 字符串生成为 style 节点
                }, {
                    loader: "css-loader" // 将 CSS 转化成 CommonJS 模块
                }, {
                    loader: "sass-loader" // 将 Scss 编译成 CSS
                }]
            }
        ]
    },
    mode: "development"
};
复制代码

 

导入scss做为模块

复制代码
//定义模块
//部分依赖lodash中的join方法
import {join} from 'lodash';
//导入模块,得到file1.txt中的文件内容,被raw-loader处理
import message from './file1.txt';
//导入样式文件
//import '../css/baseCss.css'
//导入预处理样式文件
import '../css/baseScss.scss'

//导出一个默认模块
export default function bar() {
    function component() {
        //建立DOM元素
        var element=document.createElement("h2");
        //使用join链接数组将结果写入元素的html中
        element.innerHTML=join(['Hello','Webpack','!'],' ')+"<br/>"+message;
        return element;
    }
    //在body中添加子元素
    document.body.appendChild(component());
}
复制代码

打包后运行结果:

一般,生产环境下比较推荐的作法是,使用 ExtractTextPlugin 将样式表抽离成专门的单独文件。这样,样式表将再也不依赖于 JavaScript:

复制代码
const ExtractTextPlugin = require("extract-text-webpack-plugin");

const extractSass = new ExtractTextPlugin({
    filename: "[name].[contenthash].css",
    disable: process.env.NODE_ENV === "development"
});

module.exports = {
    ...
        module
:
{
    rules: [{
        test: /\.scss$/,
        use: extractSass.extract({
            use: [{
                loader: "css-loader"
            }, {
                loader: "sass-loader"
            }],
// 在开发环境使用 style-loader
            fallback: "style-loader"
        })
    }]
}
,
plugins: [
    extractSass
]
}
;
复制代码

4.七、url-loader(路径处理器)

 Webpack 容许你在js文件中require图片 , 经过 url-loader和file-loader来预处理图片文件,将图片转换成base64编码。

安装

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

用法

url-loader 功能相似于 file-loader,可是在文件大小(单位 byte)低于指定的限制时,能够返回一个 DataURL。

import img from './image.png'

配置

复制代码
webpack.config.js

module.exports = {
    module: {
        rules: [
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 8192
                        }
                    }
                ]
            }
        ]
    }
}
复制代码

示例

webpack.config.js

复制代码
//webpack配置文件

//依赖node中的path模块
var path=require('path');

//定义一个默认模块对象
module.exports={
    entry:{app01:"./src/app01.js"},
    //设置输出结果
    output: {
        //路径,将相对路径转绝对路径
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模块名称,占位
        filename: "[name].bundle.js"
    },
    module: {
        rules: [
            {
                //如是文件名是gif,jpg,jpeg,bmp图片则匹配,不分大小写
                test:/\.(gif|jpe?g|png|bmp)/i,
                use: {
                    loader: "url-loader",
                    options: {
                        //若是图片的大小小于1024byte(B)时转换成dataUrl,base64编码
                        limit:1024,
                        fallback:"responsive-loader"
                    }
                }
            }
        ]
    }
};
复制代码

src/app01.js

复制代码
//导入大图片 404byte
import srcBig from '../img/big.jpg';
//导入小图片 100Kbyte
import srcSma from '../img/small.gif';

console.log(srcBig);
console.log(srcSma)

alert("Hello App01!");

//建立大图片DOM
var img1=document.createElement("img");
//指定url
img1.src=srcBig;
//添加到文档中
document.body.appendChild(img1);

//建立小图片DOM
var img2=document.createElement("img");
//指定url
img2.src=srcSma;
//添加到文档中
document.body.appendChild(img2);
复制代码

运行结果:

5、插件plugins

5.一、插件概要

Plugin 是用来扩展 Webpack 功能的,经过在构建流程里注入钩子实现,它给 Webpack 带来了很大的灵活性。

插件是 webpack 的支柱功能。webpack 自身也是构建于,你在 webpack 配置中用到的相同的插件系统之上!插件目的在于解决 loader 没法实现的其余事。

webpack 插件是一个具备 apply 属性的 JavaScript 对象。apply 属性会被 webpack compiler 调用,而且 compiler 对象可在整个编译生命周期访问。

复制代码
ConsoleLogOnBuildWebpackPlugin.js

const pluginName = 'ConsoleLogOnBuildWebpackPlugin';

class ConsoleLogOnBuildWebpackPlugin {
    apply(compiler) {
        compiler.hooks.run.tap(pluginName, compilation => {
            console.log("webpack 构建过程开始!");
        });
    }
}
复制代码

 

compiler hook 的 tap 方法的第一个参数,应该是驼峰式命名的插件名称。建议为此使用一个常量,以便它能够在全部 hook 中复用。

因为插件能够带参数/选项,你必须在 webpack 配置中,向 plugins 属性传入 new 实例。

根据你的 webpack 用法,这里有多种方式使用插件。

复制代码
webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); //经过 npm 安装
const webpack = require('webpack'); //访问内置的插件
const path = require('path');

const config = {
  entry: './path/to/my/entry/file.js',
  output: {
    filename: 'my-first-webpack.bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        use: 'babel-loader'
      }
    ]
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

module.exports = config;
复制代码

5.一、HTML Webpack Plugin(建立HTML插件)

该个插件的做用是用来自动生成html页面,既能够生成单个页面又能够生成多个页面,而且在生成前能够给它一些的配置参数,它会按照你想要的生成方式去生成页面。

第一步:安装

npm i html-webpack-plugin -D

第二步:在webpack.config.js里引入模块

const HtmlWebpackPlugin=require('html-webpack-plugin');

第三步:在webpack.config.js中的plugins对象里new一个实例

plugins:[
  new HtmlWebpackPlugin({参数})
]

结果

复制代码
const HtmlWebpackPlugin = require('html-webpack-plugin')
 
module.exports = {
  entry: 'index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'index_bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin()
  ]
}
复制代码

参数:

title

生成页面的titile元素

filename

生成的html文件的文件名。默认index.html,能够直接配置带有子目录

复制代码
//webpack.config.js
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    filename: 'index1.html'//可带子目录'html/index1.html'
  })
]
复制代码

template

模版文件路径

templateParameters

{Boolean|Object|Function} 容许覆盖模板中使用的参数

复制代码
//webpack.config.js
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    templateParameters: {
      title: 'xxxx',
      favicon: './favicon/index.ico',
    }
  })
]
复制代码

inject

插入的script插入的位置,四个可选值:
true: 默认值,script标签位于html文件的body底部
body: 同true
headscript标签位于html文件的head标签内
false: 不插入生成的js文件,只是生成的html文件

favicon

为生成的html文件生成一个favicon,属性值是路径

minify

html文件进行压缩。属性值是false或者压缩选项值。默认false不对html文件进行压缩。
html-webpack-plugin中集成的html-minifier,生成模板文件压缩配置,有不少配置项,这些配置项就是minify的压缩选项值。

hash

给生成的js文件尾部添加一个hash值。这个hash值是本次webpack编译的hash值。默认false;

复制代码
//webpack.config.js
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    hash: true
  })
]
//html
<script type="text/javascript" src="bundle.js?59a5ed17040d94df87fe">
//59a5ed17040d94df87fe是本次webpack编译的hash值
复制代码

cache

Boolean类型。只在文件被修改的时候才生成一个新文件。默认值true

showErrors

Boolean类型。错误信息是否写入html文件。默认true

chunks

html文件中引用哪些js文件,用于多入口文件时。不指定chunks时,全部文件都引用

复制代码
//webpack.config.js
entry: {
  index1: path.resolve(__dirname, './index1.js'),
  index2: path.resolve(__dirname, './index2.js'),
  index3: path.resolve(__dirname, './index3.js')
}
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    chunks: [index1, index2]//html文件中只引入index1.js, index2.js
  })
]
复制代码

 

excludeChunks

与chunks相反,html文件不引用哪些js文件

复制代码
//webpack.config.js
entry: {
  index1: path.resolve(__dirname, './index1.js'),
  index2: path.resolve(__dirname, './index2.js'),
  index3: path.resolve(__dirname, './index3.js')
}
...
plugins: [
  new HtmlWebpackPlugin({
    ...
    excludeChunks: [index3.js]//html文件中不引入index3.js
  })
]
复制代码

 

chunksSortMode

控制script标签的引用顺序。默认五个选项:
none: 无序
auto: 默认值, 按插件内置的排序方式
dependency: 根据不一样文件的依赖关系排序
manual: chunks按引入的顺序排序, 即属性chunks的顺序
{Function}: 指定具体的排序规则

xhtml

Boolean类型,默认falsetrue时以兼容xhtml的模式引用文件

示例:

复制代码
plugins:[
    new HtmlWebpackPlugin({
        title:'Hello app',    /*这个值对应html里的title*/
        template:'./src/template.html', //模板文件地址
        filename:'test1.html',  //文件名,默认为index.html(路径相对于output.path的值)
        inject:true,    //script标签的位置,true/body为在</body>标签前,head为在<head>里,false表示页面不引入js文件
        hash:true,  //是否为引入的js文件添加hash值
        chunks:['one'], //页面里要引入的js文件,值对应的是entry里的key。省略参数会把entry里全部文件都引入
        //excludeChunks:['one'],//页面里不能引入的js文件,与chunks恰好相反
        minify:{    //html-webpack-plugin内部集成了html-minifier
            collapseWhitespace:true,    //压缩空格
            removeAttributeQuotes:true, //移除引号
            removeComments:true,        //移除注释
        },
    }),
    //生成两个文件,分别引入两个js文件(如今是一个文件里引入了两个js)
    new HtmlWebpackPlugin({
        title:'kaivon',
        template:'./src/template.html',
        hash:true,
        filename:'test2.html',
        chunks:['two']
    })
]
复制代码

示例1:

webpack.config03.js配置文件

复制代码
//webpack配置文件

//导入用于生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin");

//依赖node中的path模块
var path=require('path');

//定义一个默认模块对象
module.exports={
    entry:{app01:"./src/app03.js"},
    //设置输出结果
    output: {
        //路径,将相对路径转绝对路径
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模块名称,占位
        filename: "[hash:8].bundle.js"
    },
    module: {
    },
    plugins: [
        //建立一个插件对象,并指定参数
        new HtmlWebpackPlugin({
            //指定生成的文件路径与名称
            filename:"../app03.html",
            //标题
            title:"Hello App03!"
        })
    ]
};
复制代码

arc/app03.js

alert("Hello App03!");

打包结果:

运行:

示例2:

webpack.config03.js配置文件

复制代码
//webpack配置文件

//导入用于生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin");

//依赖node中的path模块
var path=require('path');

//定义一个默认模块对象
module.exports={
    entry:{app01:"./src/app03.js"},
    //设置输出结果
    output: {
        //路径,将相对路径转绝对路径
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模块名称,占位
        filename: "[hash:8].bundle.js"
    },
    module: {
    },
    plugins: [
        //建立一个插件对象,并指定参数
        new HtmlWebpackPlugin({
            //指定生成的文件路径与名称
            filename:"../app03.html",
            //标题
            title:"Hello App03!",
            //指定模板
            template:"./templates/tmpl03.html",
            //模板参数,容许覆盖templates中的参数
            templateParameters:{
                content:"Hello templateParameters!",
                //重写title
                title:"Hello App03 title!",
                key:"value"
            },
            minify:{
                removeComments:true,  //移除注释
                collapseWhitespace:true,  //折叠空格
                //更新请参数https://github.com/kangax/html-minifier#options-quick-reference
            }
        })
    ]
};
复制代码

/templates/tmpl03.html 模板文件

  View Code

生成结果:

5.二、Mini-css-extract-plugin(单独提取CSS插件)

将CSS提取为独立的文件的插件,对每一个包含css的js文件都会建立一个CSS文件,支持按需加载css和sourceMap

默认状况下css是被js注入的一段style,以下所示:

只能用在webpack4中,对比另外一个插件 extract-text-webpack-plugin特色:

  • 异步加载
  • 不重复编译,性能更好
  • 更容易使用
  • 只针对CSS

目前缺失功能,HMR(热模块替换)。

  HMR解释

安装:

npm install --save-dev mini-css-extract-plugin

使用:

复制代码
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // 相似 webpackOptions.output里面的配置 能够忽略
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              // 这里能够指定一个 publicPath
              // 默认使用 webpackOptions.output中的publicPath
              publicPath: '../'
            },
          },
          'css-loader',
        ],
      }
    ]
  }
}
复制代码

高级配置:

这个插件应该只用在 production 配置中,而且在loaders链中不使用 style-loader, 特别是在开发中使用HMR,由于这个插件暂时不支持HMR

复制代码
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const devMode = process.env.NODE_ENV !== 'production';

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: devMode ? '[name].css' : '[name].[hash].css',
      chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
    })
  ],
  module: {
    rules: [
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader',
        ],
      }
    ]
  }
}
复制代码

示例:

webpack.config03.js

复制代码
//webpack配置文件

//导入用于生成html的插件
const HtmlWebpackPlugin=require("html-webpack-plugin");
//导入用于提取css的插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

//依赖node中的path模块
var path=require('path');

//定义一个默认模块对象
module.exports={
    entry:{app01:"./src/app03.js"},
    //设置输出结果
    output: {
        //路径,将相对路径转绝对路径
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模块名称,占位
        filename: "[hash:8].bundle.js"
    },
    module: {
        rules: [
            {
                test: /\.scss$/,
                use: [{
                    loader:MiniCssExtractPlugin.loader //提取css并link
                }, {
                    loader: "css-loader" // 将 CSS 转化成 CommonJS 模块
                }, {
                    loader: "sass-loader" // 将 Scss 编译成 CSS
                }]
            }
        ]
    },
    plugins: [
        //建立一个插件对象,并指定参数
        new HtmlWebpackPlugin({
            //指定生成的文件路径与名称
            filename:"../app03.html",
            //标题
            title:"Hello App03!",
            //指定模板
            template:"./templates/tmpl03.html",
            //模板参数,容许覆盖templates中的参数
            templateParameters:{
                content:"Hello templateParameters!",
                //重写title
                title:"Hello App03 title!",
                key:"value"
            },
            minify:{
                removeComments:true,  //移除注释
                collapseWhitespace:true,  //折叠空格
                //更新请参数https://github.com/kangax/html-minifier#options-quick-reference
            }
        }),
        //建立一个用于提取css的插件对象
        new MiniCssExtractPlugin({
            filename:"[name]_[hash:10].css",
            chunkFilename:"[id]"
        })
    ]
};
复制代码

src/app03.js

import '../css/baseScss.scss';

alert("Hello App03!");

打包生成的结果

复制代码
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <title>Hello App03 title!</title>
    <link href="dist/app01_1b7c11aa92.css" rel="stylesheet">
</head>
<body><h2>Hello templateParameters!</h2>
<script type="text/javascript" src="dist/1b7c11aa.bundle.js"></script>
</body>
</html>
复制代码

运行结果:

5.三、clean-webpack-plugin(删除或清理构建目录)

在用HtmlWebpackPlugin的时候时须要把dist目录删掉再去看生成的文件,clean-webpack-plugin这个插件就能够作这件事情

第一步:安装

npm i clean-webpack-plugin --save-dev

 

第二步:在webpack.config.js里引入模块

const CleanWebpackPlugin=require('clean-webpack-plugin');

 

第三步:在plugins的最前面建立清理对象

复制代码
plugins:[
new CleanWebpackPlugin(['./dist']), //这个必定要放在最上面,做用是先删除dist目录再建立新的dist目录。里面的参数为要删除的目录,放在一个数组里面
...
]
复制代码

 

在文件夹里打开dist所在的目录,并在终端里再次执行命令webpack后,会看到dist目录先被删除后又被建立。

关于clean-webpack-plugin插件的全部配置参数请参考:https://www.npmjs.com/package/clean-webpack-plugin

示例:

复制代码
const CleanWebpackPlugin = require('clean-webpack-plugin'); //installed via npm
const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
const path = require('path');
 
// the path(s) that should be cleaned
let pathsToClean = [
  'dist',
  'build'
]
 
// the clean options to use
let cleanOptions = {
  root:     '/full/webpack/root/path',
  exclude:  ['shared.js'],
  verbose:  true,
  dry:      false
}
 
// sample WebPack config
const webpackConfig = {
  entry: './path/to/my/entry/file.js',
  output: {
    filename: 'my-first-webpack.bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        loader: 'babel-loader'
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(pathsToClean, cleanOptions),
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
}
复制代码

6、DevServer开发服务器 

在实际开发中咱们可能会须要完成以下功能:

  1. 提供 HTTP 服务而不是使用本地文件预览;
  2. 监听文件的变化并自动刷新网页,作到实时预览;
  3. 支持 Source Map,以方便调试。

Webpack 原生支持上述第二、3点内容,再结合官方提供的开发工具 DevServer 也能够很方便地作到第1点。 DevServer 会启动一个 HTTP 服务器用于服务网页请求,同时会帮助启动 Webpack ,并接收 Webpack 发出的文件更变信号,经过 WebSocket 协议自动刷新网页作到实时预览。

6.一、快速开启DevServer

安装 DevServer:

npm i -D webpack-dev-server

安装成功后在项目的根目录下执行webpack-dev-server 命令, DevServer 服务器就启动了,这时你会看到控制台有一串日志输出:

Project is running at http://localhost:8080/

webpack output is served from /

如今就能够直接访问了

这意味着 DevServer 启动的 HTTP 服务器监听在 http://localhost:8080/ ,DevServer 启动后会一直驻留在后台保持运行,访问这个网址你就能获取项目根目录下的 index.html。