webpack-入门

参考:http://www.javashuo.com/article/p-gqgzutje-er.htmlcss

1.什么是webpack,为何要使用它html

  一些优秀的网站每每有许多JavaScript文件,不少依赖项,为了简化开发的复杂度,前端有不少实践方法:前端

  • 模块化,让咱们能够把复杂的程序细化为小的文件;
  • 相似于TypeScript这种在JavaScript基础上拓展的开发语言:使咱们可以实现目前版本的JavaScript不能直接使用的特性,而且以后还能转换为JavaScript文件使浏览器能够识别;
  • Scss,less等CSS预处理器

  这些方法每每有不少文件浏览器不能直接识别,须要二次处理后才能够,此时webpack应允而生node

  WebPack能够看作是模块打包机react

    它作的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用webpack

  Webpack的工做方式是:es6

    把你的项目当作一个总体,经过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的全部依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件web

2.开始使用webpack正则表达式

  2.1 开始安装webpacknpm

  Webpack可使用npm安装,新建一个空的练习文件夹(此处命名为webpack sample project),在终端中转到该文件夹后执行下述指令就能够完成安装

//全局安装
npm install -g webpack
//安装到你的项目目录
npm install --save-dev webpack

  2.2 开始前准备

    2.2.1 在这个路径的cmd中输入npm init,自动生成package.json文件写入项目的信息,若是不作正式使用能够回车默认便可

    2.2.2 在本项目中安装Webpack做为依赖包

// 安装Webpack
npm install --save-dev webpack

    2.2.3 回到以前的空文件夹,并在里面建立两个文件夹,app文件夹和public文件夹,app文件夹用来存放原始数据和咱们将写的JavaScript模块,public文件夹用来存放以后供浏览器读取的文件(包括使用webpack打包生成的js文件以及一个index.html文件)。接下来咱们再建立三个文件:

  • index.html --放在public文件夹中;
  • Greeter.js-- 放在app文件夹中;
  • main.js-- 放在app文件夹中;

    

    在index.html文件中写入最基础的html代码,它在这里目的在于引入打包后的js文件(这里咱们先把以后打包后的js文件命名为bundle.js,以后咱们还会详细讲述)

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Webpack Sample Project</title>
  </head>
  <body>
    <div id='root'>
    </div>
    <script src="bundle.js"></script>
  </body>
</html>

    咱们在Greeter.js中定义一个返回包含问候信息的html元素的函数,并依据CommonJS规范导出这个函数为一个模块:

// Greeter.js
module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = "Hi there and greetings!";
  return greet;
};

    main.js文件中咱们写入下述代码,用以把Greeter模块返回的节点插入页面。

//main.js 
const greeter = require('./Greeter.js');
document.querySelector("#root").appendChild(greeter());

    2.2.4 正式使用webpack

  webpack能够在终端中使用,在基本的使用方法以下:

# {extry file}出填写入口文件的路径,本文中就是上述main.js的路径,
# {destination for bundled file}处填写打包文件的存放路径
# 填写路径的时候不用添加{}
webpack {entry file} {destination for bundled file}

  指定入口文件后,webpack将自动识别项目所依赖的其它文件,不过须要注意的是若是你的webpack不是全局安装的,那么当你在终端中使用此命令时,须要额外指定其在node_modules中的地址,继续上面的例子,在终端中输入以下命令

# webpack非全局安装的状况
node_modules/.bin/webpack app/main.js public/bundle.js

    运行完成后就会在public文件夹中自动生成bundle.js,被index.html引用成功!至此一个完整的小webpack项目结束

  有没有以为在cmd中输入的webpack命名比较繁琐,好的,这里有较为简单的命令方法,但须要修改下配置文件package.json

{
  "name": "webpack-sample-project",
  "version": "1.0.0",
  "description": "Sample webpack project",
  "scripts": {
    "start": "webpack" // 修改的是这里,JSON文件不支持注释,引用时请清除
  },
  "author": "zhang",
  "license": "ISC",
  "devDependencies": {
    "webpack": "3.10.0"
  }
}

  以后想要启动启动webpack只需在对应的项目目录下只需npm start效果就能完整的命令效果同样

3.webpack 强大功能

  3.1 可调试

    通常经过打包后的文件,不容易找到出错的地方,对应你写的代码的位置,配置了Source maps就能帮咱们解决这个问题,经过简单的配置,webpack能够帮咱们生成Source Maps,这为咱们提供了一种对应的编译文件与源文件方法,使得编译后的代码可读性更高:配置devtool便可

devtool选项 配置结果
source-map 在一个单独的文件中产生一个完整且功能彻底的文件。这个文件具备最好的source map,可是它会减慢打包速度;
cheap-module-source-map 在一个单独的文件中生成一个不带列映射的map,不带列映射提升了打包速度,可是也使得浏览器开发者工具只能对应到具体的行,不能对应到具体的列(符号),会对调试形成不便;
eval-source-map 使用eval打包源文件模块,在同一个文件中生成干净的完整的source map。这个选项能够在不影响构建速度的前提下生成完整的sourcemap,可是对打包后输出的JS文件的执行具备性能和安全的隐患。在开发阶段这是一个很是好的选项,在生产阶段则必定不要启用这个选项;
cheap-module-eval-source-map 这是在打包文件时最快的生成source map的方法,生成的Source Map 会和打包后的JavaScript文件同行显示,没有列映射,和eval-source-map选项具备类似的缺点;

对小到中型的项目中,eval-source-map是一个很好的选项,再次强调你只应该开发阶段使用它,咱们继续对上文新建的webpack.config.js,进行以下配置:

module.exports = {
  devtool: 'eval-source-map',
  entry:  __dirname + "/app/main.js",
  output: {
    path: __dirname + "/public",
    filename: "bundle.js"
  }
}
方法构建速度更快,可是不利于调试,推荐在大型项目考虑时间成本时使用。
cheap-module-eval-source-map

  3.2 配置本地服务器

    这个本地服务器是基于node.js,须要将webpack-dev-server在项目根目录下安装

npm install --save-dev webpack-dev-server

    devserver做为webpack配置选项中的一项,如下是它的一些配置选项,更多配置可参考这里

devserver的配置选项 功能描述
contentBase 默认webpack-dev-server会为根文件夹提供本地服务器,若是想为另一个目录下的文件提供本地服务器,应该在这里设置其所在目录(本例设置到“public"目录)
port 设置默认监听端口,若是省略,默认为”8080“
inline 设置为true,当源文件改变时会自动刷新页面
historyApiFallback 在开发单页应用时很是有用,它依赖于HTML5 history API,若是设置为true,全部的跳转将指向index.html

  把这些命令加到webpack的配置文件中,如今的配置文件webpack.config.js以下所示

  

module.exports = {
  devtool: 'eval-source-map',

  entry:  __dirname + "/app/main.js",
  output: {
    path: __dirname + "/public",
    filename: "bundle.js"
  },

  devServer: {
    contentBase: "./public",//本地服务器所加载的页面所在的目录
    historyApiFallback: true,//不跳转
    inline: true//实时刷新
  } 
}

  在package.json中的scripts对象中添加以下命令,用以开启本地服务器:

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack",
    "server": "webpack-dev-server --open"
  },

  在终端中输入npm run server便可在本地的8080端口查看结果

  3.3 Loaders

    Loaders的功能就强大了,他能够将不是js的文件类型转为js让浏览器能够识别

    好比说分析转换scss为css,或者把下一代的JS文件(ES6,ES7)转换为现代浏览器兼容的JS文件,对React的开发而言,合适的Loaders能够把React的中用到的JSX文件转换为JS文件

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

  • test:一个用以匹配loaders所处理文件的拓展名的正则表达式(必须)
  • loader:loader的名称(必须)
  • include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不须要处理的文件(文件夹)(可选);
  • query:为loaders提供额外的设置选项(可选)

  不过在配置loader以前,咱们把Greeter.js里的问候消息放在一个单独的JSON文件里,并经过合适的配置使Greeter.js能够读取该JSON文件的值,各文件修改后的代码以下:

在app文件夹中建立带有问候信息的JSON文件(命名为config.json)

{
  "greetText": "Hi there and greetings from JSON!"
}

更新后的Greeter.js  

var config = require('./config.json');

module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = config.greetText;
  return greet;
};

在看如何具体使用loader以前咱们先看看Babel是什么?

  3.4 Babel

  Babel实际上是一个编译JavaScript的平台,它能够编译代码帮你达到如下目的:

  • 让你能使用最新的JavaScript代码(ES6,ES7...),而不用管新标准是否被当前使用的浏览器彻底支持;
  • 让你能使用基于JavaScript进行了拓展的语言,好比React的JSX;

  Babel的安装与配置

    Babel实际上是几个模块化的包,其核心功能位于称为babel-core的npm包中,webpack能够把其不一样的包整合在一块儿使用,对于每个你须要的功能或拓展,你都须要安装单独的包(用得最多的是解析Es6的babel-env-preset包和解析JSX的babel-preset-react包)。

// npm一次性安装多个依赖模块,模块之间用空格隔开
npm install --save-dev babel-core babel-loader babel-preset-env babel-preset-react

webpack中配置Babel的方法以下:

module.exports = {
    entry: __dirname + "/app/main.js",//已屡次说起的惟一入口文件
    output: {
        path: __dirname + "/public",//打包后的文件存放的地方
        filename: "bundle.js"//打包后输出文件的文件名
    },
    devtool: 'eval-source-map',
    devServer: {
        contentBase: "./public",//本地服务器所加载的页面所在的目录
        historyApiFallback: true,//不跳转
        inline: true//实时刷新
    },
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader",
                    options: {
                        presets: [
                            "env", "react"
                        ]
                    }
                },
                exclude: /node_modules/
            }
        ]
    }
};

如今你的webpack的配置已经容许你使用ES6以及JSX的语法了。继续用上面的例子进行测试,不过此次咱们会使用React,记得先安装 React 和 React-DOM

npm install --save react react-dom

接下来咱们使用ES6的语法,更新Greeter.js并返回一个React组件

//Greeter,js
import React, {Component} from 'react'
import config from './config.json';

class Greeter extends Component{
  render() {
    return (
      <div>
        {config.greetText}
      </div>
    );
  }
}

export default Greeter

修改main.js以下,使用ES6的模块定义和渲染Greeter模块

// main.js
import React from 'react';
import {render} from 'react-dom';
import Greeter from './Greeter';

render(<Greeter />, document.getElementById('root'));

从新使用npm start打包,若是以前打开的本地服务器没有关闭,你应该能够在localhost:8080下看到与以前同样的内容,这说明reactes6被正常打包了。

Babel的配置

Babel其实能够彻底在 webpack.config.js 中进行配置,可是考虑到babel具备很是多的配置选项,在单一的webpack.config.js文件中进行配置每每使得这个文件显得太复杂,所以一些开发者支持把babel的配置选项放在一个单独的名为 ".babelrc" 的配置文件中。咱们如今的babel的配置并不算复杂,不过以后咱们会再加一些东西,所以如今咱们就提取出相关部分,分两个配置文件进行配置(webpack会自动调用.babelrc里的babel配置选项),以下:

module.exports = {
    entry: __dirname + "/app/main.js",//已屡次说起的惟一入口文件
    output: {
        path: __dirname + "/public",//打包后的文件存放的地方
        filename: "bundle.js"//打包后输出文件的文件名
    },
    devtool: 'eval-source-map',
    devServer: {
        contentBase: "./public",//本地服务器所加载的页面所在的目录
        historyApiFallback: true,//不跳转
        inline: true//实时刷新
    },
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node_modules/
            }
        ]
    }
};
//.babelrc
{
  "presets": ["react", "env"]
}

到目前为止,咱们已经知道了,对于模块,Webpack能提供很是强大的处理功能,那那些是模块呢。

一切皆模块

Webpack有一个不可不说的优势,它把全部的文件都都当作模块处理,JavaScript代码,CSS和fonts以及图片等等经过合适的loader均可以被处理。

 

CSS

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

//安装
npm install --save-dev style-loader css-loader
//使用
module.exports = {

   ...
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader"
                    }
                ]
            }
        ]
    }
};

接下来,在app文件夹里建立一个名字为"main.css"的文件,对一些元素设置样式

/* main.css */
html {
  box-sizing: border-box;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
}

*, *:before, *:after {
  box-sizing: inherit;
}

body {
  margin: 0;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

h1, h2, h3, h4, h5, h6, p, ul {
  margin: 0;
  padding: 0;
}

咱们这里例子中用到的webpack只有单一的入口,其它的模块须要经过 importrequireurl等与入口文件创建其关联,为了让webpack能找到”main.css“文件,咱们把它导入”main.js “中,以下

//main.js
import React from 'react';
import {render} from 'react-dom';
import Greeter from './Greeter';

import './main.css';//使用require导入css文件

render(<Greeter />, document.getElementById('root'));

上面的代码说明webpack是怎么把css当作模块看待的,我们继续看一个更加真实的css模块实践。

CSS module

CSS预处理器

插件(Plugins)

相关文章
相关标签/搜索