Webpack 是当下最热门的前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。通过 loader 的转换,任何形式的资源都可以视作模块,比如 CommonJs 模块、 AMD 模块、 ES6 模块、CSS、图片、 JSON、Coffeescript、 LESS 等。

总结一下常用的功能

Webpack编译less文件

需要安装style-loader css-loader less-loader less等加载器

style-loader 把css的样式引入到html的style标签

css-loader 可以在js里面引入css文件,例如 import css from ‘file.css’

less-loader less 编译less文件

例如我们的资源文件目录如下

|- assets
|	|- js
|	|	|- index.js
|	|- style
|	|	|- common.less
|	|	|- index.less
|- index.html

common.less

html {
  color: blue;
}

index.less

@import "common.less";
body {
  background: grey;
}

index.js

import "../style/index.less"
console.log(1);

最后配置webpack.config.js

const path = require("path");
module.exports = {
    entry: {
        "index": './assets/js/index.js'
    },
    output: {
        filename: "js/[name].bundle.js",
        path: path.resolve(__dirname, "dist"),
    },
    module: {
        rules: [
            {
                test: /\.less$/i,
                use: [{
                    loader: 'style-loader'
                },{
                    loader: 'css-loader'
                }, {
                    loader: 'less-loader'
                }]
            }
        ]
    }
}

这里的output.path 配置很重要,所有的输出文件都是在这路径的基础上输出的,下文需要用到

编译需要用到style-loader,css-loader,less-loader,顺序很重要,是从后到前的,所以这里是先编译less文件,后css加载,后完成style加载

然后控制台输入 webpack就可以看到dist/js路径里面的index.bundle.js文件了

css和js文件分开

默认情况下,打包后的js会帮忙处理样式,但是某些情况下,例如css文件过大会影响其他js文件的执行,这时候可以考虑下让js和css文件分来来加载,所以需要用到的一个插件 extract-text-webpack-plugin 这个插件可以把css文件分割开,废话少说,npm安装下后先配置

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

然后在webpack.config.js中配置插件

plugins: [
    new ExtractTextPlugin('style/[name].css')
]

括号的参数就是把文件输出到相应的位置,最终路径为output.path + 括号的参数, [name].css中的name是import后的文件名,配置好插件后修改下less的规则

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

Ok,再webpack一下,文件分开了

这样正常样式没问题,但是如果样式里面引入图片呢,webpack会报错,例如上面的common.less新增个背景图片

html {
  color: blue;
  background: url("../image/toggle")
}

编译一下,我日,报错

针对这个问题,可以用file-loader加载器来解决

首先安装 npm install file-loader

在rules里面这样配置

{
    test: /\.(jpe?g|gif|svg)$/,
    loader: 'file-loader?emitFile=false&name=[name].[ext]'  // 相对于publicPath确认文件路径
}

然后再webpack一下,无报错,再看看编译后的文件

html {
  color: blue;
  background: url(toggle);
}

发现图片的url变了,从 ../image/toggle => toggle

暂时思考的解决方法有两个

1. 将图片拷贝过去,后改下配置

{
    test: /\.(jpe?g|gif|svg)$/,
    // loader: 'file-loader?emitFile=false&name=[name].[ext]'
    loader: 'file-loader?emitFile=false&name=../image/[name].[ext]'
}

看看生成的文件,路径一样了,只是没了引号,这个没关系

html {
  color: blue;
  background: url(../image/toggle);
}

2. 由于网站访问资源文件可以用绝对路径来访问,所以利用绝对路径来生成,这样图片文件没必要再拷贝一份, 方法是在output.publicPath设置/assets/, 然后loader配置为

{
    test: /\.(jpe?g|gif|svg)$/,
    loader: loader: 'file-loader?emitFile=false&name=image/[name].[ext]'
}

最后生成的资源文件路径为

background: url(/assets/image/toggle);

第三方通用模块分开打包

例如jquery是每个页面都要引入的文件,所以可以提取出来,不用每次都进行打包,需要用到的插件是CommonsChunkPlugin,配置如下

plugins: [
    new ExtractTextPlugin('style/[name].css'),
    new webpack.optimize.CommonsChunkPlugin({
        name: "vendor"
    })
]

接下来再entry入口配置下第三方通用模块

entry: {
    "vendor": ["jquery", "moment"],
    "index": './assets/js/index.js'
}

index.js文件修改为

import $ from "jquery"
import moment from "moment"

console.log($);
console.log(moment);
console.log(1);

然后再webpack一下,结果生成了两个文件index.bundle.js和vendor.bundle.js

最后打开index.html,发现报错

Uncaught ReferenceError: webpackJsonp is not defined

原因是没有把通用模块生成的文件引入进来

于是在index.bundle.js上面先引入

<script src="dist/js/vendor.bundle.js"></script>

这样就行了