08、React系列之--使用webpack管理

1、什么是webpack

webpack是一个打包工具,是一个模块加载工具,是一个构建工具,在 webpack 当中, 所有的资源都被当作是模块, js, css, 图片等等。因此, webpack 当中 js 可以引用 css, css 中可以嵌入图片 dataUrl。看下图说明了webpack的功能

webpack.jpg

2、webpack的特点

  • 1、插件丰富
  • 2、有非常多的加载器,比如加载css的是css-loader,一般都有对应的loader
  • 3、代码分割,提供按需加载的能力
  • 4、发布工具

3、webpack的优势

  • 1、webpack是以commonJs的形式来书写脚本,也全面支持AMD/CMD,方便旧的项目进行牵移。
  • 2、能模块化的不仅是Js,各种资源都可以做为模块来处理。
  • 3、 开发便捷,能替代部分 grunt/gulp 的工作,比如打包、压缩混淆、图片转base64等。
  • 4、扩展性强,插件机制完善,特别是支持 React 热插拔(react-hot-loader)的功能让人眼前一亮

4、安装和使用webpack

1、安装

  • 1、 一般情况下使用npm安装
npm install -g webpack
  • 2、使用webpack。

常规项目我们还要把webpack依赖加入到package.json中

npm init 
npm install webpack --save-dev
  • 3、想安装开发工具那么执行如下命令
npm install webpack-dev-server --save-dev

2、使用,以项目为例子演示

1、初始化一个项目,新建webpackdemo文件夹,并且初始化

mkdir webpackdemo && cd webpackdemo 
npm init

2、安装webpack

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

3、在webpackdemo文件夹中新建app和public文件夹,当然名字可以自己任意指定

mkdir app && mkdir public

4、然后在public目录中新建index.html,app目录中新建helloworld.js和main.js

webpack_project_folder.png
  • index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>webpack 入门</title>
</head>
<body>
    <div id="container"></div>
    <script src="bundle.js"></script>
</body>
</html>
  • helloworld.js
module.exports = function insertContent(){
  var hello = document.createElement('div');
  hello.textContent = "Hello world";
  return hello;
}
  • main.js
var insertContent = require('./helloworld.js');
document.getElementById('container').appendChild(insertContent()) ;

然后运行webpack app/main.js public/bundle.js(全局安装过webpack就可以这样运行),就会在public下面生成bundle.js文件,则打包就成功了

webpack_build.png

从图可以看出,webpack同时编译了main.js和helloworld.js

注://webpack非全局安装的情况打包

node_modules/.bin/webpack app/main.js public/bundle.js

打开index.html查看结果:

hello_result.png

这样我们就通过webpack成功的打包了一个文件,但是以上步骤都是要手动进行,非常不方便,我们下面来看看webpack的配置吧

5、配置webpack

webpack强大之处就在于可以灵活配置,比如一些loader和plugin都可以通过命令行来执行,但是一个个执行太TM的麻烦了,所以我们可以把相关的操作写到一个配置文件中去,这下就感觉爽歪歪了吧

1、webpack.config.js初探

在上面的例子上继续写配置文件,在根目录下新建webpack.config.js并且配置如下:

module.exports = {
  entry:  __dirname + "/app/main.js",//已多次提及的唯一入口文件
  output: {
    path: __dirname + "/public",//打包后的文件存放的地方
    filename: "bundle.js"//打包后输出文件的文件名
  }
}

然后我们在命令行执行

webpack

注:上面的命令是全局安装webpack时这样执行,如果只在项目中安装webpack那么执行:node_modules/.bin/webpack

就会得到下面结果和上面手动打包是一样的:

webpack_code.png

到此我们就掌握了一个简单的配置,并且不用手动去打包了。

2、在package.json中配置script

我们再来稍微高级一点用法,连webpack命令都不使用,我们在package.json配置script脚本如下:

{
  "name": "webpacknotedemo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start":"webpack" //配置这里 把npm的start命令指向webpack命令
  },
  "author": "JunJun",
  "license": "ISC",
  "dependencies": {
    "webpack": "^1.13.3"
  }
}

然后我们在命令行中运行npm start 也会打包出bundle.js,效果和上面一样

3、使用webpack构建本地服务器

1、在上面我们打包以后,要按f5重新刷新界面才能显示结果,想要修改一个界面自动刷新,那么我们可以安装一个服务组件。

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

2、安装完以后需要在webpack.config.js中去配置服务,否则不起作用(当然可以命令行执行其任务,我们肯定首选配置了)

devServer的配置如下:

devServe配置项 功能描述
contentBase 提供本地服务的目录,默认是根目录
inline 为true就会自动打包并且刷新浏览器,是一种启动模式
iFrame 另一种启动模式,该模式下修改代码会自动打包,但是不会自动刷新浏览器
port 服务监听的端口号
colors 设置为true则终端输出就为彩色的
historyApiFallback 在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html
module.exports = {
  entry: __dirname +"/app/main.js",//唯一的入口文件
  output:{
    path: __dirname +"/public",//打包后文件存放的目录
    filename:'bundle.js' //打包后输入的文件名
  },
  //以下是新增的配置
  devServer:{
   contentBase: "./public",//本地服务器所加载的页面所在的目录
   colors: true,//终端中输出结果为彩色
   historyApiFallback: true,//不跳转
   inline: true//实时刷新
  }
}

好了此时我们在命令行中执行:

webpack-dev-server --progress --port 8888
webpack_server.png

然后打开浏览器输入localhost:8888,则会看到页面结果

auto_save.gif

我们可以看到,我们修改了代码一保存,浏览器就会自动刷新出结果,也就验证了会自动打包和刷新浏览器。

当然了我们又在使用webpack-dev-server --progress --port 8888命令了,万一忘了命令少写一个字母,那不是麻烦,当然根据前面的经验,我们可以配置到package.json的script中

{
  "name": "webpacknotedemo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --progress --port 8888" //修改此处
  },
  "author": "JunJun",
  "license": "ISC",
  "dependencies": {
    "webpack": "^1.13.3"
  },
  "devDependencies": {
    "webpack-dev-server": "^1.16.2"
  }
}

然后我们在命令行只需要输入npm start就达到和上面一样的效果了,这里不演示了,大家自行去试验。

4、配置Loaders

1、Loaders了解和简单的React项目

Loaders可以说是webpack最让人兴奋的功能之一了,通过各种Loaders可以完成不同的功能,比如React一些合适的Loaders(Babel)可以把React的JSX文件转换成JS文件

1、Loaders是需要单独安装的而且要在webpack.config.js中去配置,要在modules关健字下进行配置,loaders配置的选项

Loaders配置项 功能描述 是否必须
test 匹配loaders所处理的文件的拓展名的正则表达式 必须
loader loader的名称 必须
include/exclude 手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹) 可选
query 为loaders提供额外的设置选项 可选

2、我们在上面例子上修改改造成React项目

  • 1、安装react和react-dom
npm install react --save
npm install react-dom --save
  • 2、由于我们要使用ES6语法和使用JSX语法,所以要装Babel

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

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

npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react
  • 3、安装了loader肯定是要配置webpack.config.js的,下面看配置
module.exports = {
  entry: __dirname +"/app/main.js",//唯一的入口文件
  output:{
    path: __dirname +"/public",//打包后文件存放的目录
    filename:'bundle.js' //打包后输入的文件名
  },
  devServer:{
   contentBase: "./public",//本地服务器所加载的页面所在的目录
   colors: true,//终端中输出结果为彩色
   historyApiFallback: true,//不跳转
   inline: true//实时刷新
 },
 //新增加部分
 module:{
   loaders:[
   //babel配置
   {
     test:/\.js$/,
     exclude: /node_modules/,
     loader: 'babel',
     query: {
        presets: ['es2015','react']
     }
   }
 ]
 }
}

  • 4、修改main.js
import React from 'react' ;
import ReactDOM from 'react-dom' ;

import Hello  from './helloworld.js';

ReactDOM.render(
  <Hello />,
  document.getElementById('container')
);

  • 5、修改helloworld.js
import React from 'react';
class Hello extends React.Component{
    render(){
        return(
            <div>
                hello world
            </div>
        )
    }
}

module.exports = Hello
  • 6、在命令行执行npm start,查看效果
es6_notfind.png

我靠竟然报错了,不过不怕,我们来解决,解决这个问题,就是在根目录新建一个.babelrc 输入以下内容

//.babelrc
{
  "presets": ["react", "es2015"]
}

然后运行npm start ,再查看浏览器,完美输入Hello world

这样我们就简单的创建了一个React项目了

2、使用css

一个页面没有css那只是一个垃圾,所以我们看如何使用css的loader

还是在上面React的例子上去继续

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

1、安装

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

2、修改webpack.config.js

module.exports = {
  entry: __dirname +"/app/main.js",//唯一的入口文件
  output:{
    path: __dirname +"/public",//打包后文件存放的目录
    filename:'bundle.js' //打包后输入的文件名
  },
  devServer:{
   contentBase: "./public",//本地服务器所加载的页面所在的目录
   colors: true,//终端中输出结果为彩色
   historyApiFallback: true,//不跳转
   inline: true//实时刷新
 },
 module:{
   loaders:[
   //babel配置
   {
     test:/\.js$/,
     exclude: /node_modules/,
     loader: 'babel',
   },
   //新增加的配置
   {
        test: /\.css$/,
        loader: 'style!css?modules'//添加对样式表的处理
   }
 ]
 }
}

注意:上面我们添加了一个?modules,这个可以不添加,但是你想模块化使用,比如在每个js中import进来这个css文件,那么就要添加上?modules

解释一下css module

css modules 的技术就意在把JS的模块化思想带入CSS中来,通过CSS模块,所有的类名,动画名默认都只作用于当前模块,也就是把css给模块化了,就像是React中的一个个的组件一样,然后组合着使用,通过import来使用

3、在app目录下添加style.css

.root {
  background-color: orange;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
}
.button{
  background-color: #ffeecc;
  border-width: 2px;
  width:100px;
  margin: 10px;
  border-color: red;
  border-radius: 8px;
}

4、修改helloworld.js

这次修改的量比较大,我们做一个有意义的事情,光helloworld也没有意思


import React from 'react';
//通过import来引进样式
import styles from './styles.css' ;
class Hello extends React.Component{

constructor(props) {
  super(props);
  this.state = {
    name:''
  };
}

  render(){
      return(
      <div className={styles.root}>
        <h2>用户登录</h2>
         <form ref='addForm' action="#">
            <p>
                <label htmlFor="name">姓名:</label><input type="text" id="name" ref="name" placeholder="请输入用户名"/>
            </p>
            <p>
               <label htmlFor="pass"> 密码:</label><input type="password" id="pass" ref="pass" placeholder="请输入用户名"/>
            </p>

            <input type="submit" value="登录" onClick={this._login.bind(this)} className={styles.button}/>

            <input type="reset" value="清空" className={styles.button}/>
            <div>
                {this.state.name?"欢迎"+this.state.name+"登录!!!":null}
            </div>
         </form>

      </div>
        )
    }

    _login(){
        let name = this.refs.name.value;
        let pass = this.refs.pass.value ;
        if(name.length==0 ||pass.length==0){
            alert('用户名或密码不能为空')
        }else{
          this.setState({
              name:name
          })
        }
    }
}

export default  Hello

上面是一个简单的登录界面,我们可以看到我们通过import引入了style样式,然后通过style.xxx来设置样式

<font color='red'>注:</font>由于class是React中的关键字,所以我们设置style的时候不能使用calss,而要使用className,同理也不能使用for要使用htmlFor,比如label中

5、npm start来看结果

如果不出什么问题就会看到下面的页面

login_simple.gif

可以看到我们设置的css样式起作用了,按钮和背景都有变化了

图片显示使用url-loader 和file-loader配合使用,然后图片就用require('xxx.png')来引用

PS:由于文章中使用的webpack和demo中的webpack版本不一致,会导致webpack.config.js配置会有不同,这是版本所致,所以不要说文章中的配置是错误的,demo中使用的的webpack版本是2.2.1,而文章中所使用的webpack版本是1.13.3,webpack2和wepack1的配置还是有点区别的。

填坑之旅

1、在webpack中使用使用以下属性

static defaultProps = {
     haha:"text" 
};

static propTypes = {
     prop: React.PropTypes.Type
};

报类似于如下错

webpack_stage0.png

解决办法就是安装babel-preset-stage-0

npm i babel-preset-stage-0 --save

然后配置.babelrc添加"stage-0"即可

{
  "presets": ["react", "es2015","stage-0"]
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容

  • 无意中看到zhangwnag大佬分享的webpack教程感觉受益匪浅,特此分享以备自己日后查看,也希望更多的人看到...
    小小字符阅读 8,160评论 7 35
  • GitChat技术杂谈 前言 本文较长,为了节省你的阅读时间,在文前列写作思路如下: 什么是 webpack,它要...
    萧玄辞阅读 12,689评论 7 110
  • 最近在学习 Webpack,网上大多数入门教程都是基于 Webpack 1.x 版本的,我学习 Webpack 的...
    My_Oh_My阅读 8,180评论 40 247
  • webpack 介绍 webpack 是什么 为什么引入新的打包工具 webpack 核心思想 webpack 安...
    yxsGert阅读 6,463评论 2 71
  • 无意中看了一段话:窗上洒满着白月的当儿,我愿意关了灯,坐下来沉默一些时候,就在这沉默中,忽然像有警钟似的来到我的心...
    贝加尔胡阅读 283评论 0 2