webpack -h
webpack -v
webpack []
Babel
npm install --save-dev babel-loader @babel-core @babel/preset-env
babel舍弃了以前的babel-*-*
的命名方式,改成了@babel/*-*
@babel/preset-env 针对语法
Babel Polyfill 和 Babel Runtime Transform 针对函数和方法
npm install babel/polyfill --save
Babel Polyfill
为全局垫片 有种全局变量污染的感觉
npm install babel-polyfill --save
真实项目的使用
Babel Runtime Transform
为局部垫片 为开发框架准备
npm install babel/plugin-transform-runtime --save-dev
npm install babel/runtime --save
使用:
app.js:
import 'babel-polyfill'
babel/runtime:
{
"presets": [
["@babel/preset-env", {
"targets":{
"browsers": ["> 1%", "last 2 versions"]
}
}]
],
"plugins": ["@babel/transform-runtime"]
}
Babel Presets 一些规范的总结
es2015
es2016
es2017
env 包含 es2015 es2016 es2017 以及最近的
babel-preset-react 关于react相关的规范
babel-preset-stage 0-3 规范还没发布的几个阶段都在里面
npm install @babel/preset-env --save-dev 如果安装最新的loader用这句
npm install babel-preset-env --save-dev 如果安装的普通的loader用这句
配置babel
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets:
['@babel/preset-env', {
targets:{
browsers: ['> 1%', 'last 2 versions']
}
}]
}
},
exclude: '/node_module/'
}
targets 可以指定babel转换的版本
targets.browsets
targets.browsers: ‘last 2 versions’ 最后两个版本(主流浏览器最后的两个版本)
targets.browsers: ‘>1%’ 可以使用百分比指定版本(全球1占有率为百分之1的浏览器都得支持)
browserslist 数据来源这个项目
Can I use 数据来自这个项目
typescript-loader的支持
npm i typescript ts-loader --save-dev 这个loader是官方提供的
npm i typescript awesome-typescript-loader --save-dev 第三方提供的
配置tsconfig.json
webpack-config.js
官网/docs/handbook/compiler-options.html
常用选项
compilerOptions
{
"compilerOptions": {
"module": "commonjs", // commonjs 包含es6 es7的import
"target": "es5", //转换的支持的成簇
"allowJs": true //是否可以支持js语法
},
"include": [
"./src/ts/*"
],
"exclude": [
"./node_modules"
]
}
对一个js的文件,引用时如果需要有类型提醒, 需要安装它的@types/*版本
第二种: Typings npm install typings
然后使用 typings的命令 typings install lodash
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"allowJs": true,
"typeRoots": [
"./node_modules/@type",
"./typings/modules" //告诉文件去哪找申明文件
]
},
"include": [
"./src/ts/*"
],
"exclude": [
"./node_modules"
]
}
提取公共代码
场景:
单页应用
单页应用 + 第三方依赖
多页应用 + 第三方依赖 + webpack生产代码
commonsChunkPlugin
webpack.optimize.CommonsChunkPlugin
webpack 3.x
entry: {
'pageA': './src/pageA',
'pageB': './src/pageB',
'vendor': ['lodash']
}
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'common', //提取 pageA和pageB中重复的代码
minChunks: 2,
chunks: ['pageA', 'pageB'] //如果不写这个, 会打包报错
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor', //单独提取lodash
minChunks: Infinity
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest', //提取wepback代码
minChunks: Infinity
})
]
webpack 4.x
https://webpack.js.org/plugins/split-chunks-plugin/
代码分割 和 懒加载
webpack methods
require.ensure
- []: dependencies
- callback
- errorCallback
- chunName
require.include
ES 2015 Lader Spec
System.import() -> import() 后者取代前者
import() -> Promise 返回一个promise对象 webpack 3.x 后支持
webpack import function
通过注释的形式告诉浏览器怎么去加载
import(
/*webpackChunkName: async-chunk-namem*/
/*webpackMode: lazy*/
modulename
)
场景:
分离业务代码 和 第三方依赖
分离业务代码 和 业务公共代码 和 第三方依赖
分离首次加载 和 访问后加载的代码
require.ensure 方式
require.include('./moduleA')
var page = 'subPageA'
//require.ensure 的时候不会去加载, 只有等require('')后才会加载
if(page === 'subPageA') {
require.ensure(['./subPageA'], function() {
var subPageA = require('./subPageA')
}, 'subPageA')
} else {
require.ensure(['./subPageB'], function() {
var subPageB = require('./subPageB')
}, 'subPageB')
}
require.ensure([], function() {
var _ = require('loadsh')
_.join([1,2,3,4], '5')
}, 'vendor')
export default 'page3'
结合多页面 共同引入的 公共业务代码 抽取
new webpack.optimize.CommonsChunkPlugin({
async: 'async-common',
children: true,
minchunks: 2
})
处理css
sytle-loader
style-loader/url
style-loader/useable
这么写 会把css单独打包成一个文件通过link引入
{
test: /\.css$/,
use: ['style-loader/url','file-loader']
}
{
test: /\.css$/,
use: ['style-loader/useable','css-loader']
}
可以在被浏览器运行环境中调用的,即使是打包之后的
import base from './csss/base.css'
base.use() 使用这个css
base.unuse() 不使用这个css
style-loader
options: {
insertInto: '#app', // 插入的地方
singleton: true, //是否只使用一个style标签
transfrom: './css.transform.js' //指向一个文件,可以在这个文件中进行一些配置
}
css.transform.js
//此文件在打包的时候不执行,在css即将插入浏览器的时候执行
//作用是可以根据浏览器的环境来选择插入css
//有几个import ‘*/css’ 就执行几次这个
module.exports = function(css) {
//do something
console.log(window.innerWidth)
if(window.innerWidth >= 768) {
return css.replace('red', 'green')
}else {
return css.replace('red','orange')
}
}
webpack-server
Module Hot Reloading
保持应用的数据状态
节省调试时间(不需要重新刷新浏览器)
样式调试更快
devServer.hot = tue
webpack.HotModuleReplacementPlugin
webpack.NamedModulesPlugin 路径
module.hot
module.hot.accept
module.hot.decline 拒绝给你的模块热更新(接受一个数组)
css 需要使用style-loader 不能使用插件提取出来
hotOnly: true
使用方法:
devServer: {
hot: true,
hotOnly: true //正对js
}
plugins: [
new webpack.HotModuleReplaceentPlugin(),
new webpack.NamedModulesPlugin() // 显示路径
]
js file
(对于单个文件)
if(module.hot){
module.hot.accept()
}
(对于单个模块)当引入一个模块,这个模块返回一个节点,这个引入的模块每次更新,都会导致那个文件追加一个节点
解决:
componentsA:
export compentsA function() {
return `
<ul>
<li>11</li>
</ul>
`
}
import compentsA from 'componentsA'
document.body.appendChild(compoents)
if(module.hot) {
module.hot.accept('./compoentsA', function() {
app.removeChild(list)
let ComponentsA = require('componentsA').compentsA
let newList = ComponentsA()
app.appendChild(newlist)
list = newLIst
})
}
一般的项目中不会这么麻烦, 向vue, react , angular 会解决这种情况
Source Map 调试
用户写的less sass …
es6 ts … 在显示在浏览器中的时候,会进行编译,导致开发的代码和调试的代码不一致,所以用source Map来做一个映射
配置:Devtool
webpack.SourceMapDevToolPlugin
webpack.EvalSourceMapDevToolPlugin
Devtool 配置:
Development
- eval
- eval-source-map
- cheap-eval-source-map(推荐)
- cheap-module-eval-source-map
Procuction
- source-map (推荐)
- hidden-source-map
- nosource-source-map
css source-map
- css-loader.option.sourcemap
- less-loader.option.sourcemap
- sass-loader.option.sourcemap
webpack file:
devServer: {
devtool: 'eval'
}
source-map: 需要注释: new webpack.optimize.UglifyJsPlugin()
关于css source-map的配置
比如less 需要给每一个处理的loader加上sourceMap: true
test: /\.less$/,
use: [
{
loader: 'style-loader',
options: {
singleton: true, //当使用这个为true时,sourceMap不起作用(坑)
sourceMap: true
}
},{
loader: 'css-loader',
options: {
importLoader: 2,
sourceMap: true
}
},{
loader: ‘postcss-loader',
options: {
ident: 'postcss',
sourceMap: true,
plugins: [
require('postcss-cssnext')()
]
}
},{
loader: 'less-loader',
options: {
sourceMap: true,
}
}
]
EsLint 检查代码格式
webpack config
.eslintrc.* 或者 package.json 中的eslintConfig
Javascript Standard Style(https://standardjs.com/)
- eslint-config-standard
- eslint-plugin-promise
- eslint-plugin-standard
- eslint-plugin-import
- eslint-plugin-node
- eslint-plugin-xxx
eslint-loader
7. options.failOnWarning
8. options.failOnError
9. options.formatter
10. options.outputReport
devServer.overlay
npm install eslint eslint-loader eslint-plugin-html eslint-friendly-formatter --save-dev
test: /\.js$/,
include: [path.resolve(__dirname, 'src')],
exclude: [path.resolve(__dirname, 'src/libs')],
use: [
{
loader: 'babel-loader',
optiosn: {
presets: ['env']
}
},{
loader: 'eslint-loader',
options: {
formatter: require('eslint-friendly-formatter')
}
}
]
plugins: [
new webpack.ProvidePlugin({
$: 'jquery'
})
]
.eslintrc.js file:
module.exports = {
root: true,
extends: 'standard',
plugins: [
'html'
],
env: {
borwser: true,
node: true
},
globals: {
$: true
},
rules: {
indent: ['error', 4], // error or warning
'eol-last': ['error', 'nev']
}
}
安装检查规范
npm eslint-config-standard eslint-plugin-promise eslint-plugin-standard eslint-plugin-import eslint-plugin-node
如果需要在浏览器中显示格式规范的错误信息
devServer: {
overlay: true
}
开发环境和生产环境
开发环境
- 模块热更新
- sourceMap
- 接口代理
- 代码规范检查
生产环境
5. 提取公用代码
6. 压缩混淆
7. 文件压缩或是Base64编码
8. 去除无用的代码
共同点
9. 同样的入口
10. 同样的代码处理(loader处理)
11. 同样的解析配置
如何做?
webpack-merge
- webpack.dev.conf.js
- webpack.prod.conf.js
- webpack.common.conf.js