webpackの学习随记(一)

webpack

https://fakefish.github.io/react-webpack-cookbook/
http://webpack.github.io/
https://segmentfault.com/a/1190000005742122

webpack简介

事实上它是一个打包工具,而不是像RequireJS或SeaJS这样的模块加载器,通过使用Webpack,能够像Node.js一样处理依赖关系,然后解析出模块之间的依赖,将代码打包。

Webpack 只是一个模块合并器!也就是说你可以设置他去加载任何你写的匹配,只要有一个加载器。

webpack.config.js 简单例子

var webpack = require('webpack');
var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');

module.exports = {
    entry: {
        entry1: './entry/entry1.js',
        entry2: './entry/entry2.js'
    },
    output: {
        path: __dirname,
        filename: '[name].entry.js'
    },
    resolve: {
        extensions: ['', '.js', '.jsx']
    },
    module: {
        loaders: [{
            test: /\.js$/,
            loader: 'babel-loader'
        }, {
            test: /\.jsx$/,
            loader: 'babel-loader!jsx-loader?harmony'
        }]
    },
    plugins: [commonsPlugin]
};
  • entry:指定打包的入口文件,每有一个键值对,就是一个入口文件
    output:配置打包结果,path定义了输出的文件夹,filename则定义了打包结果文件的名称,filename里面的[name]会由entry中的键(这里是entry1和entry2)替换。
  • resolve:定义了解析模块路径时的配置,常用的就是extensions,可以用来指定模块的后缀,这样在引入模块时就不需要写后缀了,会自动补全。
  • module:定义了对模块的处理逻辑,这里可以用loaders定义了一系列的加载器,以及一些正则。当需要加载的文件匹配test的正则时,就会调用后面的loader对文件进行处理,这正是webpack强大的原因。比如这里定义了凡是.js结尾的文件都是用babel-loader做处理,而.jsx结尾的文件会先经过jsx-loader处理,然后经过babel-loader处理。当然这些loader也需要通过npm install安装。
  • plugins: 这里定义了需要使用的插件,比如commonsPlugin在打包多个入口文件时会提取出公用的部分,生成common.js。

当然Webpack还有很多其他的配置,具体可以参照http://webpack.github.io/docs/

开始webpack之旅

配置安装

1、node和npm:安装到最新,官网https://nodejs.org/en/

2、创建package.json:问题随便,之后可以改

npm init

3、安装webpack

//安装
npm i webpack --save-dev
//运行
node_modules/.bin/webpack

4、配置webpack.config.js

var path = require('path');

module.exports = {
    entry: path.resolve(__dirname, 'app/main.js'),
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'bundle.js',
    },
};

5、打包配置,package.json

"scripts": {
    "build": "webpack"
}

运行

npm run build 

打包 build.js

注:npm 会自动找到webpack;如果需要考虑未知环境,可以采用gulp-webpack解决方案。

工作流

利用webpack-dev-server,创建服务,替换npm run build。

1、下载安装

npm i webpack-dev-server --save

2、package.json配置

{
  "scripts": {
    "build": "webpack",
    "dev": "webpack-dev-server --devtool eval --progress --colors --hot --content-base build"
  }
}
  • webpack-dev-server - 在 localhost:8080 建立一个 Web 服务器。
  • --devtool eval - 为你的代码创建源地址。当有任何报错的时候可以让你更加精确地定位到文件和行号。
  • --progress - 显示合并代码进度。
  • --colors - Yay,命令行中显示颜色!
  • --content-base build - 指向设置的输出目录。

3、测试运行

npm run dev

http://localhost:8080

4、自动刷新
当运行 webpack-dev-server 的时候,它会监听你的文件修改。当项目重新合并之后,会通知浏览器刷新。

①index.html需要和build.js 处在同一目录下,引入build.js
②在webpack.config.js中增加一个刷新入口点

entry: [
  'webpack/hot/dev-server',
  'webpack-dev-server/client?http://localhost:8080',
  path.resolve(__dirname, 'app/main.js')
],

文件引入

1、模块引入方式

ES6 模块

import MyModule from './MyModule.js';

CommonJS

var MyModule = require('./MyModule.js');

AMD

define(['./MyModule.js'], function (MyModule) {

});

2、路径

相对路径是相对当前目录,绝对路径是相对入口文件。

// ES6 相对路径
import utils from './../utils.js';

// ES6 绝对路径
import utils from '/utils.js';

// CommonJS 相对路径
var utils = require('./../utils.js');

// CommonJS 绝对路径
var utils = require('/utils.js');

注:文件后缀,你不需要去特意去使用 .js,但是他能够更让你更清楚你正引入的档案。因為你可能有一些 .js 文件和一些 .jsx 文件,甚至一些图片和 css 可以用 Webpack 來引入。加入文件后缀,可以让你清楚地区分你引入的是 node_modules 或特定档案还是一般文件档案。

ReactJS

配置ReactJS

1、下载安装

//安装react
npm install react --save
npm install react-dom --save
//安装babel-loader  
npm install babel-loader --save-dev
npm install babel-core --save-dev
npm install babel-preset-es2015 --save-dev  //支持ES2015
npm install babel-preset-react --save-dev //支持jsx
npm install babel-preset-stage-0 --save-dev //支持ES7
//但是还不够
npm install babel-polyfill --save
/*
Polyfilla是一个英国产品,在美国称之为Spackling Paste(译者注:刮墙的,在中国称为腻子).记住这一点就行:把旧的浏览器想象成为一面有了裂缝的墙.这些[polyfills]会帮助我们把这面墙的裂缝抹平,还我们一个更好的光滑的墙壁(浏览器)
*/
npm install babel-runtime  --save
npm install babel-plugin-transform-runtime --save-dev
/*减少打包的时候重复代码,以上要注意是放在dev还是非dev上!*/

注:babel 6.0+;ES6及jsx编译

2、webpack.config.js 配置

//在入口添加polyfill
entry[
'babel-polyfill',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8080',
path.resolve(__dirname,'app/main.js')
]
//在webpack.config.js的module.exports = {}里面增加
module:{
loaders:[{
    'loader':'babel-loader',
    exclude:[
        //在node_modules的文件不被babel理会
        path.resolve(__dirname,'node_modules'),
    ],
    include:[
        //指定app这个文件里面的采用babel
        path.resolve(__dirname,'app'),
    ],
    test:/\.jsx?$/,
    query:{
        plugins:['transform-runtime'],
        presets:['es2015','stage-0','react']
    }
}]
}

3、运行打包

//打包
npm run build 
//运行
npm run dev

优化重合并

在开发环境中,最理想的是编译最多 200 到 800 毫秒的速度,取决于你在开发的应用。

为了不让 Webpack 去遍历 React JS 及其所有依赖,你可以在开发中重写它的行为。

webpack.config.js

var path = require('path');
var node_modules = path.resolve(__dirname, 'node_modules');
var pathToReact = path.resolve(node_modules, 'react/dist/react.min.js');

config = {
    entry: ['webpack/hot/dev-server', path.resolve(__dirname, 'app/main.js')],
    resolve: {
        alias: {
          'react': pathToReact
        }
    },
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'bundle.js',
    },
    module: {
        loaders: [{
            test: /\.jsx?$/,
            loader: 'babel'
        }],
        noParse: [pathToReact]
    }
};

module.exports = config;
  • 每当 "react" 在代码中被引入,它会使用压缩后的 React JS 文件,而不是到 node_modules 中找。
  • 每当 Webpack 尝试去解析那个压缩后的文件,我们阻止它,因为这不必要。

注意!这个是设置一个压缩和发布的 React 版本,结果你可能会失去 propTypes 基础类型检查!

Flow

进行类型检测

flowcheck-loader

CSS、Fonts和Images加载

Webpack允许像加载任何代码一样加载 CSS,你可以为每个组件把所有你的 CSS 加载到入口主文件中来做任何事情。

1、加载器

  • css-loader:遍历 CSS 文件,然后找到 url() 表达式然后处理。
  • style-loader:把原来的 CSS 代码插入页面中的一个 style 标签中。

下载安装加载器:

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

2、webpack.config.js配置

{
  test: /\.css$/, // Only .css files
  loader: 'style!css' // Run both loaders
}

3、加载css方式

  • 合并加载,放在入口js下引入。
  • 懒加载,每个组件引入自身定制的css文件,使用不同命名空间。
  • 内联样式style

注!当 Webpack-dev-server 在 浏览器自动刷新 下运行的时候,CSS 也会自动更新,不过有点不同的是,当你改变了一个 CSS 文件,属于那个文件的标签会更新新的内容但不会刷新。

加载LESS和SASS

安装less或sass模块

npm install less --save
npm install sass --save

1、加载器

less-loader 或 sass-loader

npm install less-loader --save-dev
或
npm install sass-loader --save-dev

2、webpack.config.js配置

 // LESS
{
  test: /\.less$/,
  loader: 'style!css!less'
},

// SASS
{
  test: /\.scss$/,
  loader: 'style!css!sass'
}

3、引入

  • 相对或绝对路径,类似 css 引入 ,webpack会自动找出,并识别依赖。

  • 也可以直接从 node_module 中加载less。

      import '~bootstrap/less/bootstrap'
    

内联Image

直到 HTTP/2 你才能在应用加载的时候避免设置太多 HTTP 请求。根据浏览器不同你必须设置你的并行请求数,如果你在你的 CSS 中加载了太多图片的话,可以自动把这些图片转成 BASE64 字符串然后内联到 CSS 里来降低必要的请求数,这个方法取决与你的图片大小。你需要为你的应用平衡下载的大小和下载的数量,不过 Webpack 可以让这个平衡十分轻松适应。

1、安装
会将路径转为BASE64字符串;把 CSS 中的 “url()” 像其他 require 或者 import 来处理。

安装url-loader

npm install url-loader --save-dev

安装file-loader

npm install file-loader --save-dev

2、配置

{
  test: /\.(png|jpg)$/,
  loader: 'url?limit=25000'
}

url-loader 传入的 limit 参数是告诉它图片如果不大于 25KB 的话要自动在它从属的 css 文件中转成 BASE64 字符串。

内联字体

就像内联图片一样来内联字体。

字体类别:(eot | woff | woff2 | ttf | svg | png | jpg)等

配置

{
  test: /\.(eot|woff|woff2|ttf|svg|png|jpg)(\?v=[\d\.]+)?$/,
  loader: 'file?name=files/[hash].[ext]'
}
或
 {
  test: /\.woff$/,
  loader: 'url?limit=100000'
}

部署策略

发布配置

1、配置package.json脚本,设置npm run deploy

"scripts": {
    "deploy": "NODE_ENV=production webpack -p --config webpack.production.config.js"
  },

用生产(线上)参数运行 Webpack 来指向另一个配置文件。我们也使用了环境变量 “production” 来让我们的模块自动去优化。

2、webpack.config.js配置案例

var path = require('path');
var node_modules_dir = path.resolve(__dirname, 'node_modules');

var config = {
  entry: path.resolve(__dirname, 'app/main.js'),
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    loaders: [{
      test: /\.js$/,

      // There is not need to run the loader through
      // vendors
      // 这里再也不需通过任何第三方来加载
      exclude: [node_modules_dir],
      loader: 'babel'
    }]
  }
};

module.exports = config;

3、运行

npm run deploy 

webpack运行生成模式

合并成单文件

单入口模式:

  • 应用很小
  • 更新应用很少
  • 不关心初始加载时间

webpack.production.config.js

var path = require('path');
var config = {
  entry: path.resolve(__dirname, 'app/main.js'),
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    loaders: [{
      test: /\.js$/,
      loader: 'babel'
    }]
  }
};

module.exports = config;

分离应用和第三方依赖

1、条件

  • 当你的第三方的体积达到整个应用的 20% 或者更高的时候。
  • 更新应用的时候只会更新很小的一部分
  • 你没有那么关注初始加载时间,不过关注优化那些回访用户在你更新应用之后的体验。
  • 有手机用户。

2、webpack.production.config.js

var path = require('path');
var webpack = require('webpack');
var node_modules_dir = path.resolve(__dirname, 'node_modules');

var config = {
  entry: {
    app: path.resolve(__dirname, 'app/main.js'),

    // Since react is installed as a node module, node_modules/react,
    // we can point to it directly, just like require('react');
    // 当 React 作为一个 node 模块安装的时候,
    // 我们可以直接指向它,就比如 require('react')
    vendors: ['react']
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'app.js'
  },
  module: {
    loaders: [{
      test: /\.js$/,
      exclude: [node_modules_dir],
      loader: 'babel'
    }]
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js')
  ]
};

module.exports = config;

这些配置会在 dist/ 文件夹下创建两个文件:app.js 和 vendors.js,两个文件均需要引入到html中。

多重入口

1、应用条件

  • 你的应用有多种不同的用户体验,但是他们共享了很多代码。
  • 你有一个使用更少组件的手机版本
  • 你的应用是典型的权限控制,你不想为普通用户加载所有管理用户的代码。

2、webpack.production.config.js

var path = require('path');
var webpack = require('webpack');
var node_modules_dir = path.resolve(__dirname, 'node_modules');

var config = {
  entry: {
    app: path.resolve(__dirname, 'app/main.js'),
    mobile: path.resolve(__dirname, 'app/mobile.js'),
    vendors: ['react'] // 其他库
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js' // 注意我们使用了变量
  },
  module: {
    loaders: [{
      test: /\.js$/,
      exclude: [node_modules_dir],
      loader: 'babel'
    }]
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js')
  ]
};

module.exports = config;

这个配置会在 dist/ 文件夹下创建三个文件:app.js、mobile.js和vendors.js,大部分的代码在mobile.js文件中,也有一部分在 app.js 中,不过这是我们需要的,我们不会在同一个页面中同时加载 app.js 和 mobile.js。

懒加载入口文件

1、运用条件

  • 你有一个相对比较大的应用,可以让用户可以访问应用的不同部分。
  • 你非常关注初始渲染时间

2、结合 react-router 或 es6 require.ensure,通过路由实现懒加载。

import React from 'react';
import Feed from './Feed.js';

class App extends React.Component {
  constructor() {
    this.state = { currentComponent: Feed };
  }
  openProfile() {
    require.ensure([路由], () => {
      var Profile = require('./Profile.js');
      this.setState({
        currentComponent: Profile
      });
    });
  }
  render() {
   return (
      return <div>{this.state.currentComponent()}</div>
    );
  }
}
React.render(<App/>, document.body);

不需要在config配置中设置懒加载依赖,Webpack 会自动理解他们,然后分析你的代码

插件篇

自动补全CSS3前缀——autoprefixer

官方是这样说的:Parse CSS and add vendor prefixes to CSS rules using values from the Can I Use website
,也就是说它是一个自动检测兼容性给各个浏览器加个内核前缀的插件。

举个栗子:最新的弹性盒模型flux
实际代码:

:fullscreen a {
    display: flex
}

插件自动补充后

a {
    display: -webkit-box;
    display: -webkit-flex;
    display: -ms-flexbox;
    display: flex
}

效果显而易见,我们可以更专注于css布局和美化,而不需要花过多的精力都写相同的外码而加上不同的前缀,也减少了冗余代码。

1、安装下载

npm install autoprefixer --save-dev
npm install postcss-loader --save-dev

2、配置

var autoprefixer = require('autoprefixer');
module.exports={
  //其他配置这里就不写了

  module:{
    loaders:[
    {
      test:/\.css$/,
      //在原有基础上加上一个postcss的loader就可以了
      loaders:['style-loader','css-loader','postcss-loader']
        /*{
      test: /\.css$/, // Only .css files
        loader: 'style!css!postcss' // loaders
      }*/
    }]
  },
  postcss:[autoprefixer({browsers:['last 2 versions']})]

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

推荐阅读更多精彩内容

  • 版权声明:本文为博主原创文章,未经博主允许不得转载。 webpack介绍和使用 一、webpack介绍 1、由来 ...
    it筱竹阅读 10,933评论 0 21
  • 无意中看到zhangwnag大佬分享的webpack教程感觉受益匪浅,特此分享以备自己日后查看,也希望更多的人看到...
    小小字符阅读 8,081评论 7 35
  • GitChat技术杂谈 前言 本文较长,为了节省你的阅读时间,在文前列写作思路如下: 什么是 webpack,它要...
    萧玄辞阅读 12,613评论 7 110
  • 在现在的前端开发中,前后端分离、模块化开发、版本控制、文件合并与压缩、mock数据等等一些原本后端的思想开始...
    Charlot阅读 5,386评论 1 32
  • 对销售人员和客户来说,成交这个环节是最有压力的。所有的客户都有过消极的购买经历,比如他们买了一样东西,不久之后就发...
    新胡杨阅读 468评论 0 0