Webpack v4 使用 Webpack低版本编译后的文件

webpackJsonp

The JSONP function used by webpack for async loading of chunks.

Webpack 使用JSONP按需加载 chunks,这个函数的名字默认为 webpackJsonp

在之前版本的 webpack 中,webpackJsonp 是一个函数:

问题

在一个项目中如果同时需要同时运行 Webpack v4Webpack v1-3 编译后的模块,会导致命名冲突。

webpack v1

1
2
3
4
5
6
7
8
/******/(function(modules) { // webpackBootstrap
/******/ // install a JSONP callback for chunk loading
/******/ var parentJsonpFunction = window["webpackJsonp"];
/******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules) {
/******/ ...
/******/ };
/******/ ...
/******/ })

但在 webpack v4 中变成了一个数组

1
(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{150:function(e,t,u){....

如果在同一网页上使用多个 webpack不同版本编译后的文件,就会产生冲突,导致异步 chunks 无法加载。

解决方案

正确的做法是使用 output.jsonpFunction 方法修改 JSONP 的默认名,解决冲突。

output.jsonpFunction

string

Only used when target is web, which uses JSONP for loading on-demand chunks.

A JSONP function name used to asynchronously load chunks or join multiple initial chunks (CommonsChunkPlugin, AggressiveSplittingPlugin).

This needs to be changed if multiple webpack runtimes (from different compilation) are used on the same webpage.

If using the output.library option, the library name is automatically appended.

评论和共享

优雅的使用 SVG ICON

创建 Icon 组件

index.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import cs from 'classnames'

import styles from './style.module.css'
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('RESOURCES/icons/svg', false, /\.svg$/)
requireAll(req)

class Icon extends PureComponent {
render () {
const { name, className } = this.props
return (
<svg
className={cs(
className,
styles['svg-icon']
)}
aria-hiidden="true"
>
<use xlinkHref={`#icon-${name}`} />
</svg>
)
}
}

Icon.propTypes = {
name: PropTypes.string.isRequired,
className: PropTypes.object
}

export default Icon

style.module.css

1
2
3
4
5
6
7
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}

使用 svg-sprite

安装 svg-sprite-loader,这是一个 webpack loader ,可以将多个 svg 打包成 svg-sprite

1
npm install svg-sprite-loader --save-dev

配置 webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...
{
test: /\.svg$/,
loader: 'svg-sprite-loader',
include: [svgPath],
options: {
symbolId: 'icon-[name]'
}
},
{
test: /\.(png|jpe?g|gif|svg)$/,
loader: 'url-loader',
exclude: [svgPath],
options: {
...
}
}
...

更进一步优化 SVG

安装 svgo

1
npm install svgo --save-dev

修改 package.json

1
2
3
4
{
"svgo": "node ./node_modules/svgo/bin/svgo src/**/*.svg"

}

评论和共享

组成

  • 先写一个 JavaScript 构造函数
  • 在构造函数的原型上添加 apply 方法,传入 compiler
  • 在传入的 compiler 上挂载钩子事件。
  • 钩子函数中传入 compilation 和一个回调函数。
  • 功能完成后调用 webpack 提供的回调函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 命名函数
function MyExampleWebpackPlugin() {

};

// 在它的 prototype 上定义一个 `apply` 方法。
MyExampleWebpackPlugin.prototype.apply = function(compiler) {
// 指定挂载的webpack事件钩子。
compiler.plugin('webpacksEventHook', function(compilation /* 处理webpack内部实例的特定数据。*/, callback) {
console.log("This is an example plugin!!!");

// 功能完成后调用webpack提供的回调。
callback();
});
};

compiler

compiler 对象代表了完整的 webpack 环境配置。这个对象在启动 webpack 时被一次性建立,并在所有可操作的设置中被配置,包括原始配置,loader 和插件。当在 webpack 环境中应用一个插件时,插件将收到一个编译器对象的引用。可以使用它来访问 webpack 的主环境。

compilation

Compilation 实例继承于 compiler, compilation 对象代表了一次单一的版本构建和生成资源。当运行 webpack 开发环境中间件时,每当检测到一个文件变化,一次新的编译将被创建,从而生成一组新的编译资源。一个编译对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。编译对象也提供了很多关键点回调供插件做自定义处理时选择使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
{
"errors":[], //错误字符串的数组
"warnings":[], //警告字符串的数组
"version":"1.3.7", // 用来编译的 webpack 的版本
"hash":"b4806b1be53e47fbab31", // 编译使用的 hash
"time":3080, // 编译耗时 (ms)
"assetsByChunkName":{
// 用作映射的 chunk 的名称
"main":"b4806b1be53e47fbab31.js"
},
"assets":[
// asset 对象 (asset objects) 的数组
{
"name":"59e68da5e8cbc0ba28bd706801d425ba.jpg",
"size":672,
"chunks":[],
"chunkNames":[],
"emitted":true
},
{
"name":"b4806b1be53e47fbab31.js",
"size":571644,
"chunks":[0],
"chunkNames":["main"],
"emitted":true
}
],
"chunks":[
// chunk 对象 (chunk objects) 的数组
{
"id":0,
"rendered":true,
"initial":true,
"entry":true,
"size":539740,
"names":["main"],
"files":["b4806b1be53e47fbab31.js"],
"parents":[],
"origins":[
{
"moduleId":0,
"module":"...",
"moduleIdentifier":"...",
"moduleName":"./app/entry.js",
"loc":"",
"name":"main",
"reasons":[

]
}
]
}
],
"modules":[
// 模块对象 (module objects) 的数组
],
"children":[]
}

Asset对象

每一个 assets 对象都表示一个编译出的 output 文件。 assets 都会有一个共同的结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"entry": true, // 表示这个 chunk 是否包含 webpack 的运行时
"files": [
// 一个包含这个 chunk 的文件名的数组
],
"filteredModules": 0, // 当 `exclude`传入`toJson` 函数时,统计被无视的模块的数量
"id": 0, // 这个 chunk 的id
"initial": true, // 表示这个 chunk 是开始就要加载还是 懒加载(lazy-loading)
"modules": [
// 模块对象 (module objects)的数组
"web.js?h=11593e3b3ac85436984a"
],
"names": [
// 包含在这个 chunk 内的 chunk 的名字的数组
],
"origins": [
// 下文详述
],
"parents": [], // 父 chunk 的 ids
"rendered": true, // 表示这个 chunk 是否会参与进编译
"size": 188057 // chunk 的大小(byte)
}

Chunk对象

每一个 chunks 表示一组称为 chunk 的模块。每一个对象都满足以下的结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"entry": true, // 表示这个 chunk 是否包含 webpack 的运行时
"files": [
// 一个包含这个 chunk 的文件名的数组
],
"filteredModules": 0, // 见上文的 结构
"id": 0, // 这个 chunk 的id
"initial": true, // 表示这个 chunk 是开始就要加载还是 懒加载(lazy-loading)
"modules": [
// 模块对象 (module objects)的数组
"web.js?h=11593e3b3ac85436984a"
],
"names": [
// 包含在这个 chunk 内的 chunk 的名字的数组
],
"origins": [
// 下文详述
],
"parents": [], // 父 chunk 的 ids
"rendered": true, // 表示这个 chunk 是否会参与进编译
"size": 188057 // chunk 的大小(byte)
}

模块对象

缺少了对实际参与进编译的模块的描述,这些数据又有什么意义呢。每一个在依赖图表中的模块都可以表示成以下的形式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"assets": [
// asset对象 (asset objects)的数组
],
"built": true, // 表示这个模块会参与 Loaders , 解析, 并被编译
"cacheable": true, // 表示这个模块是否会被缓存
"chunks": [
// 包含这个模块的 chunks 的 id
],
"errors": 0, // 处理这个模块发现的错误的数量
"failed": false, // 编译是否失败
"id": 0, // 这个模块的ID (类似于 `module.id`)
"identifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // webpack内部使用的唯一的标识
"name": "./lib/index.web.js", // 实际文件的地址
"optional": false, // 每一个对这个模块的请求都会包裹在 `try... catch` 内 (与ESM无关)
"prefetched": false, // 表示这个模块是否会被 prefetched
"profile": {
// 有关 `--profile` flag 的这个模块特有的编译数据 (ms)
"building": 73, // 载入和解析
"dependencies": 242, // 编译依赖
"factory": 11 // 解决依赖
},
"reasons": [
// 见下文描述
],
"size": 3593, // 预估模块的大小 (byte)
"source": "// Should not break it...\r\nif(typeof...", // 字符串化的输入
"warnings": 0 // 处理模块时警告的数量
}

每一个模块都包含一个 理由 (reasons) 对象,这个对象描述了这个模块被加入依赖图表的理由。每一个 理由 (reasons) 都类似于上文 chunk objects中的 来源 (origins):

1
2
3
4
5
6
7
8
9
{
"loc": "33:24-93", // 导致这个被加入依赖图标的代码行数
"module": "./lib/index.web.js", // 所基于模块的相对地址 context
"moduleId": 0, // 模块的 ID
"moduleIdentifier": "(webpack)\\test\\browsertest\\lib\\index.web.js", // 模块的地址
"moduleName": "./lib/index.web.js", // 可读性更好的模块名称 (用于 "更好的打印 (pretty-printing)")
"type": "require.context", // 使用的请求的种类 (type of request)
"userRequest": "../../cases" // 用来 `import` 或者 `require` 的源字符串
}

错误与警告

错误 (errors) 和 警告 (warnings) 会包含一个字符串数组。每个字符串包含了信息和栈的追溯:

评论和共享

本地开发服务器

安装 webpack-dev-server

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

修改配置文件 webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
module.exports = {
...
devServer: {
contentBase: "./", //告诉服务器在哪里,从提供内容
port: 9000, //端口
inline: true, //
compress: false, //是否启用gzip压缩
historyApiFallback: false, //将404定向到固定位置
}
...
};

修改 package.json

1
2
3
4
5
6
7
{
...
"scripts": {
"dev": "webpack-dev-server",
},
...
}

webpack HotModuleReplacement

1
npm install --save react-hot-loader@next

Create a .babelrc

1
2
3
4
5
6
7
8
9
{
"presets": [
["es2015", {"modules": false}],
"react"
],
"plugins": [
"react-hot-loader/babel"
]
}

webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
const { resolve } = require('path');
const webpack = require('webpack');

module.exports = {
context: resolve(__dirname, 'src'),

entry: [
'react-hot-loader/patch',
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'./index.js'
// the entry point of our app
],
output: {
filename: 'bundle.js',
path: resolve(__dirname, 'dist'),
publicPath: '/'
},

devtool: 'inline-source-map',

devServer: {
hot: true,
// enable HMR on the server
},

module: {
rules: [
{
test: /\.jsx?$/,
use: [ 'babel-loader', ],
exclude: /node_modules/
//注意,这里不能使用 options: {} 应该在项目根目录创建 .babelrc
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader?modules', ],
},
],
},

plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(),
// prints more readable module names in the browser console on HMR updates
],
};

src/index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import React from 'react';
import ReactDOM from 'react-dom';

import { AppContainer } from 'react-hot-loader';
// AppContainer is a necessary wrapper component for HMR

import App from './components/App';

const render = (Component) => {
ReactDOM.render(
<AppContainer>
<Component/>
</AppContainer>,
document.getElementById('root')
);
};

render(App);

// Hot Module Replacement API
if (module.hot) {
module.hot.accept('./components/App', () => {
render(App)
});
}

webpack 仪表盘

安装 webpack-dashboard

1
npm install webpack-dashboard --save-dev

修改配置文件 webpack.config.js

1
2
3
4
5
6
7
8
9
10
// Import the plugin:
var DashboardPlugin = require('webpack-dashboard/plugin');

// If you aren't using express, add it to your webpack configs plugins section:
plugins: [
new DashboardPlugin({ port: 3001 })
]

// If you are using an express based dev server, add it with compiler.apply
compiler.apply(new DashboardPlugin());

HTML代码热加载

webpack-dev-server 只能监控入口文件(JS/LESS/CSS/IMG)的变化,因此 HTML 文件的变化必须依赖插件来进行监控。
安装 html-webpack-plugin

1
npm install html-webpack-plugin --save-dev

修改配置文件 webpack.config.js, 把 index.html 加入监控

1
2
3
4
5
6
7
8
9
10
11
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
...
plugins: [
new HtmlWebpackPlugin({ // html代码热加载
template: './index.html'
}),
],
...
};

自动打开浏览器

安装 open-browser-webpack-plugin

1
npm install open-browser-webpack-plugin --save-dev

修改配置文件 webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
var OpenBrowserPlugin = require('open-browser-webpack-plugin');

module.exports = {
...
plugins: [
new OpenBrowserPlugin({ //自动打开浏览器
url: 'http://localhost:9000'
})
],
...
};

配置 json 加载器

安装 json-loader

1
npm install json-loader --save-dev

修改配置文件 webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
module.exports = {
...
module: {
rules: [{
test: /\.json$/,
use: [
{ loader: "json-loader" },
]
}]
}
};

创建 config.json 文件,内容如下

1
2
3
4
{
"name": "demo",
"type": "HTML5"
}

使用

1
2
3
var config = require('../config.json')

console.log(config.name);

配置 LESS 编译

安装 less style-loader css-loader less-loader

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module.exports = {
...
module: {
rules: [
{
test: /\.less$/,
use: [
{ loader: "less-loader" },
{ loader: "style-loader" },
{
loader: "css-loader",
options: {
modules: true,
}
}
]
},
}
};

配置 Babel 编译

安装 babel-core babel-loader babel-preset-es2015

1
npm install babel-core babel-loader babel-preset-es2015 --save-dev

修改配置文件 webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
module.exports = {
...
module: {
rules: [{
test: /\.js$/, //babel解析器
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}]
}
};

配置 React

安装 babel-core babel-loader babel-preset-es2015 babel-preset-react

1
npm install babel-core babel-loader babel-preset-es2015 babel-preset-react --save-dev

修改配置文件 webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
...
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: [
path.resolve(__dirname, "/node_modules/")
],
query: {
presets: ['es2015','react']
}
}
]
}
};

配置 jQuery 解析器

安装 jquery

1
npm install jquery --save-dev

修改配置文件 webpack.config.js

1
2
3
4
5
6
7
8
9
10
module.exports = {
...
plugins: [
new webpack.ProvidePlugin({ //jquery解析器
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery"
})
]
};

配置 js 代码压缩

修改配置文件 webpack.config.js, 在 plugin 中添加 webpack.optimize.UglifyJsPlugin 模块

1
2
3
4
5
6
7
8
9
10
11
12
13
var webpack = require('webpack');
var uglifyJsPlugin = webpack.optimize.UglifyJsPlugin;

module.exports = {
...
plugins: [
new uglifyJsPlugin({ //js代码压缩
compress: {
warnings: false
}
})
]
};

配置 eslint 语法解析

安装 esline

1
npm install eslint eslint-loader eslint-friendly-formatter eslint-plugin-html babel-eslint eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-standard --save-dev

在项目根目录下添加 eslint 配置文件 .eslintrc.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// http://eslint.org/docs/user-guide/configuring
module.exports = {
root: true,
parser: 'babel-eslint',
parserOptions: {
sourceType: 'module'
},
env: {
browser: true,
},
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
extends: 'standard',
// required to lint *.vue files
plugins: [
'html'
],
// add your custom rules here
'rules': {
// allow paren-less arrow functions
'arrow-parens': 0,
"indent": [2, 4],//缩进风格
'no-undef': 0,
// allow async-await
'generator-star-spacing': 0,
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
}
}

修改配置文件 webpack.config.js
安装 url-loader

1
npm install url-loader --save-dev

修改配置文件 webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
module.exports = {
...
module: {
loaders: [{
test: /\.(png|jpg)$/,
use: [
{
loader: "url-loader"
}
]
}]
}
};

配置图片

1
2
3
4
5
6
7
module.exports = {
...
module: {
loaders: [
]
}
};

配置 normalize.css

安装 normalize.css

1
npm install normalize.css --save

使用

1
import 'normalize.css';

配置 iconfont

  • http://www.iconfont.cn/ 选图标,添加到购物车,下载代码。
  • 有三种方式,推荐使用 unicode 方式,将字体文件和 iconfont.css 放到项目中
  • iconfont.css 修改字体路径例如 url('../font/iconfont.woff?t=1494653894295') 形式
  • 修改 webpack.config.js 配置 url-loader

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    module.exports = {
    ...
    module: {
    loaders: [{
    test: /\.(woff|svg|eot|ttf)\??.*$/,
    use: [
    {
    loader: "url-loader"
    }
    ]
    }]
    }
    };
  • 使用 iconfont

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import React, { Component } from 'react';
    import Font from '../../style/iconfont.css';

    class Banner extends Component{
    render(){
    return (
    <div className={Style.historyButtonBack+" "+Font.iconfont+" "+Font["icon-houtui"]}></div>
    )
    }
    }

评论和共享

Webpack 学习笔记

webpack学习笔记

  • 基础打包命令:

    1
    webpack {entry file/入口文件} {destination for bundled file/存放bundle.js的地方}
  • 通过配置文件使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    module.exports = {
    devtool: 'eval-source-map', //配置生成Source Maps,选择合适的选项
    entry: __dirname + "/app/main.js", //已多次提及的唯一入口文件
    output: {
    path: __dirname + "/public", //打包后的文件存放的地方
    filename: "bundle.js" //打包后输出文件的文件名
    },
    module: { //在配置文件里添加JSON loader
    loaders: [
    {
    test: /\.json$/,
    loader: "json"
    },
    {
    test: /\.js$/,
    exclude: /node_modules/,
    loader: 'babel', //在webpack的module部分的loaders里进行配置即可
    query: {
    presets: ['es2015','react']
    }
    }
    ]
    },
    devServer: {
    contentBase: "./public", //本地服务器所加载的页面所在的目录
    colors: true, //终端中输出结果为彩色
    historyApiFallback: true, //不跳转
    inline: true //实时刷新
    }
    }

    打包命令:

    1
    webpack

    也可以将此命令封装到npm中

    注:“__dirname”是node.js中的一个全局变量,它指向当前执行脚本所在的目录。

  • 生成Source Maps(使调试更容易)

    | 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选项具有相似的缺点;|

  • 使用webpack构建本地服务器

    安装:

    1
    npm install --save-dev webpack-dev-server
配置:

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

运行服务器:
1
webpack-dev-server
  • Loaders

    Loaders需要单独安装并且需要在webpack.config.js下的modules关键字下进行配置,Loaders的配置选项包括以下几方面:

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

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

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

      Babel包的安装

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

      babel-core — 核心功能


      babel-preset-es2015 — 解析Es6


      babel-preset-react — 解析JSX

      为了测试Babel安装是否成功需要安装React和React-DOM

      1
      npm install --save react react-dom
#### Babel的配置选项
<p>
Babel其实可以完全在webpack.config.js中进行配置,但是考虑到babel具有非常多的配置选项,
在单一的webpack.config.js文件中进行配置往往使得这个文件显得太复杂,
因此一些开发者支持把babel的配置选项放在一个单独的名为 ".babelrc" 的配置文件中。
我们现在的babel的配置并不算复杂,不过之后我们会再加一些东西,因此现在我们就提取出相关部分,
分两个配置文件进行配置(webpack会自动调用.babelrc里的babel配置选项),如下:
</p>
1
2
3
4
//.babelrc
{
"presets": ["react", "es2015"]
}
  • CSS


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

    • 安装

      1
      npm install --save-dev style-loader css-loader
<p style="color:#ff5656">注:感叹号的作用在于使同一文件能够使用不同类型的loader</p>
  • CSS module

    把JS的模块化思想带入CSS中来,通过CSS模块,所有的类名,动画名默认都只作用于当前模块。相同的类名也不会造成不同组件之间的污染。
    CSS modules 也是一个很大的主题,有兴趣的话可以去官方文档查看更多消息

  • CSS预处理器

    这里使用postcss来示范

    1
    2
    npm install --save-dev postcss-loader autoprefixer
    //autoprefixer 自动添加前缀的插件
  • 插件(Plugins)

    Loaders和Plugins常常被弄混,但是他们其实是完全不同的东西,可以这么来说,
    loaders是在打包构建过程中用来处理源文件的(JSX,Scss,Less..),一次处理一个,
    插件并不直接操作单个文件,它直接对整个构建过程其作用。

    • BannerPlugin:(编译后的文件前添加信息)
      1
      2
      3
      plugins: [
      new webpack.BannerPlugin("Copyright Flying Unicorns inc.") //在这个数组中new一个就可以了
      ],
* HtmlWebpackPlugin (依据一个简单的模板,帮你生成最终的Html5文件)

1
npm install --save-dev html-webpack-plugin
1
2
3
4
5
6
7
8
//webpack
var HtmlWebpackPlugin = require('html-webpack-plugin');

plugins: [
new HtmlWebpackPlugin({
template: __dirname + "/app/index.tmpl.html"//new 一个这个插件的实例,并传入相关的参数
})
],
* HtmlWebpackPlugin (热更新插件)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
npm install --save-dev babel-plugin-react-transform react-transform-hmr

//webpack.config.js -> plugins
new webpack.HotModuleReplacementPlugin()//热加载插件

//.babelrc ->
{
"presets": ["react", "es2015"],
"env": {
"development": {
"plugins": [["react-transform", {
"transforms": [{
"transform": "react-transform-hmr",

"imports": ["react"],

"locals": ["module"]
}]
}]]
}
}
}
  • 产品阶段的构建

    创建一个“webpack.production.config.js”的文件,在里面加上基本的配置,它和原始的webpack.config.js很像
    1
    2
    //package.json -> scripts
    webpack --config ./webpack.production.config.js --progress
  • 优化插件

    • OccurenceOrderPlugin :为组件分配ID,通过这个插件webpack可以分析和优先考虑使用最多的模块,并为它们分配最小的ID
    • UglifyJsPlugin:压缩JS代码;
    • ExtractTextPlugin:分离CSS和JS文件

      OccurenceOrderPlugin 和 UglifyJsPlugin 是内置插件

      1
      npm install --save-dev extract-text-webpack-plugin
      1
      2
      3
      //webpack.production.config.js -> plugins
      new webpack.optimize.OccurenceOrderPlugin(),
      new webpack.optimize.UglifyJsPlugin(),

评论和共享

  • 第 1 页 共 1 页
作者的图片

Archie Shi

Nothing to say


Front-End Development Engineer