webpack入门指南

demo地址:https://github.com/yonglijia/...javascript

首先来介绍下webpack是干吗的。 css

webpack简单的来说,是一个前端模块化管理和打包工具,能够将你的文件所依赖的js,css,node包等所有打包成一个bundle文件,而且可以处理各类模块之间依赖问题。在webpack的世界里,一切皆模块!但它又不只仅是一个打包工具。它不只可以轻松处理你项目中的依赖关系和加载顺序,还能让这个流程更加智能化,自动化。html

webpack的使用,最复杂的一部分是莫过于它的配置项。webpack经过你的配置项,放置全部与打包相关的信息。一个基本的配置包括前端

module.exports = {
        entry: '',
        output: {},
        module: {
            rules: []
        },
        plugins: [],
};

咱们能够这样理解这几个配置:java

你若是要打包一个文件,那首先要指定文件的地址,也就是entry;打包以后放在那里呢,也就是output;打包过程当中文件要通过怎么样的处理,也就是rules中的loader;如何可以使webpack打包更快,体积更小呢,也就是plugins。这些配置相辅相成,紧密结合node

这些配置命名须要写入webpack.config.js中。在项目中,执行webpack,就会自动引用这个文件。react

下面咱们详细介绍下这些配置。创建一个简单的项目,包含webpack

1.jpg

testWebpck.jsgit

module.exports = function() {
    var testDiv = document.createElement('div');
    testDiv.textContent = "hello world";
    return testDiv;
};

index.jsgithub

var testWebpack = require('./testWebpack.js');
document.querySelector("#root").appendChild(testWebpack());

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>learn webpack</title>
</head>
<body>
<div id="root">

</div>
<script src="build/bundle.js"></script>
</body>
</html>

webpack.config.js

module.exports = {
    entry: __dirname+"/app/index.js",//打包的js
    output: {
        path: __dirname + "/build",//打包后的文件存放的地方
        filename: "bundle.js",//打包后bundle文件的文件名
    },
    module: {
        rules: []
    },
    plugins: [],
};

咱们在项目根目录中,执行webpack

2.jpg

浏览器打开index.html,能够看到hello world!。修改testWebpck, 修改成“hello webpack!”,从新执行webpack,再次打开index.html,能够看到浏览器中变为hello webpack!

开发环境

咱们可使用webpack-dev-server,来构建一个本地服务器,经过这个服务器,监听你的代码,实时更新你修改的内容。

首先

npm install webpack-dev-server

而后在package.json中添加脚本

"scripts": {
    "start": "webpack-dev-server --config webpack.config.js",
 },

npm的start命令是一个特殊的脚本,直接使用npm start就能够执行其对于的命令;而若是不是start,想要在命令行中运行时,须要这样用npm run {script name}npm run build

执行npm start,在浏览器中输入http://127.0.0.1:8080,能够看到咱们所看到的如出一辙的页面。

Webpac-dev-server须要添加devServer配置

devServer{
  hot:true,//
  inline:true,//
  port:8080,//默认8080
  proxy:{//接口代理
    '/xxx/**': {//接口匹配的地址
                target:"代理地址",
                secure: false
            },
  }
}

目前为止,咱们已经使用wepack成功完成了一个文件的打包,而且能在开发环境中使用。可是未使用任何的loader,plugin,由于这里面涉及到的文件还太少,种类也很少。下面来一步步丰富这个小项目,引入所须要的配置。

咱们在项目中引入css

index.css

#root{
    border:1px solid red;
}

在index.js中引入require('./index.css');

执行npm start

7.jpg
这时已经报错,提示咱们要引入相应的loader来处理css。是时候展现真正的技术了——— loader。

loader

loader是什么呢?正如咱们上面所讲的是,它用来如何处理咱们的打包文件的;如今若是不引入loader,那就没法处理css文件。loader不只仅是处理css,还能够用来css的预处理、js的中使用ES6等高级语法处理成浏览器能兼容的格式。文件、图片、json等处理,都须要用到loader;通过loader的处理,这些文件可以很好的打入打包后的bundle中。

一个loader所须要的配置包括四个方面

test、loader、includer/exclude、query

首先来看个示范

{
    test: /\.js$|\.jsx$/,
    loader: 'babel-loader',
    exclude: /(node_modules|bower_components)/,
    query: {
            presets: ['es2015', 'react'],
            plugins: ['transform-class-properties', 'lodash']
    },
},

test是一个正则表达式,它用来匹配适用于loader文件的扩展名

loader中是loader的名称,1.x版本不须要加上“-loader”,日后的版本须要加上“-loader”.

这两个都是必须添加的配置,下面两个是可选的。

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

query:为loaders提供额外的设置

CSS - loader

那咱们来根据上面的配置来设置loader,来处理css。

webpack提供两个工具处理样式表,css-loader 和 style-loader;安装这两个npm包,修改咱们的配置

module.exports = {
    entry: __dirname+"/app/index.js",//打包的js
    output: {
        path: __dirname + "/build",//打包后的文件存放的地方
        filename: "bundle.js",//打包后bundle文件的文件名
    },
    module: {
        rules: [ {test: /\.css$/, loaders: ["style-loader", "css-loader"]},]//引入多个loader,loader要写成loaders,属性为一个数组,存放各个loader
    },
    plugins: [],
};

执行npm start,在浏览器中咱们发现,helllo world中已经添加上了红色的边框了。

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

有一点要注意的是:loader是有顺序的。webpack确定是先将全部css模块依赖解析完获得计算结果再建立style标签。所以应该把style-loader放在css-loader的前面(webpack loader的执行顺序是从右到左),顺序不对,会报错。

这样咱们基本上使用了完成了一个loader的基本配置。

咱们来配置下添加其余loader的配置项:

  • 处理图片

须要同时安装url-loader和file-loader

{test: /\.(?:jpg|gif|png)$/, loader: 'url-loader?limit=10240&name=images/[name]-[hash:10].[ext]'},

url-loader与file-loader的工做方式类似,若是文件的体积比byte limit小,就能返回Data Url。若是图片比limit小,将直接以base64的形式内联在代码中。若是图片比limit(以bytes为单位)大,那么webpack就会使用file-loader去处理文件,而且全部的查询参数都会传递给file-loader。

咱们想把js和图片打包成不一样的文件夹,须要把output配置项修改一下

output: {
        path: __dirname + "/build",//打包后的文件存放的地方
        filename: "js/bundle.js",//打包后bundle文件的文件名
    },

在项目app文件夹中分别添加两个图片,一个大于1024,一个小于1024,circle_loaction.png,data_update.gif

添加上面的配置,执行weibpack,发现一个有一个文件在build/images中生成。

4.png

这里面有一个路径的点须要注意:

若是在output中添加publicPath,好比说/xxx/

module.exports = {
    entry: __dirname+"/app/index.js",//打包的js
    output: {
          publicPath: '/xxx/',
        path: __dirname + "/build",//打包后的文件存放的地方
        filename: "bundle.js",//打包后bundle文件的文件名
    },
    module: {
        rules: [
          {test: /\.css$/, loaders: ["style-loader", "css-loader"]},
          {test: /\.(?:jpg|gif|png)$/, loader: 'url-loader?limit=10240&name=images/[name]-[hash:10].[ext]'},
        ]
    },
    plugins: [],
};

那咱们访问http://127.0.0.1:8080,发现bundle找不到。这是由于加上publicPath以后,访问内存中的文件bundle都须要加上/xxx/(但实际上引用的是内存中的文件,既不是/build/js/也不是/xxx/)。因此要修改html中的引用地址方能使用。

<script src="xxx/js/bundle.js"></script>

publicPath表示资源的发布地址,加上该属性后,打包文件中全部经过相对路径引用的资源都会被配置的路径所替换。

若是此时修改index.css

#root{
    border:1px solid red;
    height: 350px;
    background-image:url("./data_update.gif");
}

./data_update.gif 就会自动替换成xxx/images/data_update-37a1914078.gif。

path和publicPath的区别

path:/build/js

publicPaht:/online/

  • 线下环境

path是打包后文件存放的路径,不能用于html中的js引用

publicPath表示的是资源发布的路径。自动指向path编译目录(/online/ => /build/js/),html中引用js文件时,必须引用此虚拟路径。

  • 线上环境

webpack进行编译(固然是编译到/build/js/),咱们须要把目录(/build/js/)下的文件,所有复制到/online/目录下(注意:不是去修改index.html中引用bundle.js的路径)

  • 处理jsx文件

webpack不能直接处理jsx,须要借助于babel.
babel堪称神器,被誉为下一代 JavaScript 语法的编译器。用它,你能够不用等浏览器的支持,就可使用最新的标准的语法。使用它能够解析jsx的语法。对于babel,不作过多介绍。

首先安装

npm install --save-dev babel-cli babel-preset-env babel-core babel-loader babel-preset-es2015 babel-preset-react react react-dom

建立 .babelrc

{
  "presets": ["react","es2015"]
}

添加loader

{
     test: /\.js$|\.jsx$/,
     exclude: /(node_modules|bower_components)/,
     loader: 'babel-loader',
}

修改index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>learn webpack</title>
</head>
<body>
    <div id="root">

    </div>
    <div id="react">

    </div>
    <script src="build/js/index.js"></script>
    <script src="build/js/testReact.js"></script>
</body>
</html>

添加testWebpack.jsx,

import React from 'react';
import ReactDOM from 'react-dom';

class TestReact extends React.Component{
    constructor(props){
        super(props);
    }
    render(){
        return <div>this is a react div
            <img src={require('./data_update.gif')}/>
        </div>
    }
}
ReactDOM.render(<TestReact/>,document.getElementById('react'))

修改配置

module.exports = {
    entry: {
        index :__dirname+"/app/index.js",
        testReact:__dirname+"/app/testReact.jsx",
    },
    output: {
        path: __dirname + "/build",//打包后的文件存放的地方
        filename: "js/[name].js"//打包后输出文件的文件名
    },
    module: {
        rules: [
            {test: /\.css$/, loaders: ["style-loader", "css-loader"]},
            {test: /\.(?:jpg|gif|png)$/, loader: 'url-loader?limit=10240&name=images/[name]-[hash:10].[ext]'},
            {
                test: /\.js$|\.jsx$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader',
            }
        ]
    },
    plugins: [],
};

这里咱们设置了两个入口文件,而且打包成不一样的js,这个js的名字和他们自己的js的名字相同,经过filename: "js/[name].js"指定。

7.jpg

这样设置完咱们就完成了使用babel-loader处理jsx文件。

稍微展开一点entry:

entry 有三种类型字符串,数组和对象

  1. entry:"xxx/index.js",

  2. entry:["xxx/index.js","xxx/index2.js"],

  3. entry:{
    index:"xxx/index.js",
    index2:"xxx/index2.js"
    },

plugin

下面咱们介绍下,如何添加插件,使咱们的打包工程更快,更智能。

先介绍下一些经常使用的插件。

  • uglifyjs-webpack-plugin :JS压缩

var webpack = require('webpack');
var UglifyJSPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
    entry: {
        index :__dirname+"/app/index.js",
        testReact:__dirname+"/app/testReact.jsx",
    },
    output: {
        path: __dirname + "/build",//打包后的文件存放的地方
        filename: "js/[name].js"//打包后输出文件的文件名
    },
    module: {
        rules: [
            {test: /\.css$/, loaders: ["style-loader", "css-loader"]},
            {test: /\.(?:jpg|gif|png)$/, loader: 'url-loader?limit=10240&name=images/[name]-[hash:10].[ext]'},
            {
                test: /\.js$|\.jsx$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader',
            }
        ]
    },
    plugins: [
      new UglifyJSPlugin(),
    ],
};

咱们这时候打开build/js中的js文件,发现里面都被压缩混淆了。

  • DefinePlugin:定义全局变量

  • Hot Module Replacement:

    在webpack中实现HMR很简单,只须要两个配置

    1. 添加new webpack.HotModuleReplacementPlugin()

    2. 修改脚本 "start": "webpack-dev-server --config webpack.config.js",

插件分为内置和外置的,不过用法都是大同小异的。不一样的插件,配置参数也不同。

其余配置

  • devtool:这个是用来配置soucemap的类型,在开发的时候调试特别有用。里面的配置特别多,后面会单独介绍这个地方。

  • resolve:配置短路径引用

    resolve: {
            alias: {
                module: path.resolve(APP_PATH, 'module'),
                component: path.resolve(APP_PATH, "component"),
                service: path.resolve(APP_PATH, "service"),
                page: path.resolve(APP_PATH, "page"),
                node_modules: path.resolve(ROOT_PATH, 'node_modules')
            },
            extensions: ['.js', '.jsx', '.json', '.scss']
        },

    使用这个选项的话,你能够直接使用好比require('page/index'),其实就是path.resolve(APP_PATH, "page")+'/index',extensions是用来匹配所要引用的文件类型,匹配以index开头的 ['.js', '.jsx', '.json', '.scss']文件,若是没有,就会报错。

这篇文章权当个入门文档,里面还有不少须要一一深刻挖掘的,好比devtool到底选择哪一个最好,怎么使项目的打包更快,怎么使用dll等等,后续会一点一点的写。

相关文章
相关标签/搜索