@GivenCui
2017-06-14T16:19:23.000000Z
字数 7663
阅读 801
webpack
a) js的模块打包(module bundler)工具, Code Splitting代码分割,实现按需加载,也可以加载各种资源(loader)
b) 兼容AMD,CommonJS(Node),ES6模块语法
c) 部分自动化任务,如热更新, 压缩等
入口(entry)
输出(output)
loader
插件(plugins)
# 当前目录右键打开git-bash
$ mkdir webpack-test
$ cd webpack-test
$ npm init -y
$ npm install webpack --save-dev / yarn add webpack -D/--dev
# 用atom编辑器打开当前目录
$ atom ./
/* Node的CommonJS模式 */
// hello.js
var world = require('./world');
function hello () {
}
// world.js
function world (){
}
module.exports = world;
/* ES6的module模式 不用安装babel也支持 */
// hello.js
import world from './world'; // ES6
function hello(arg) {
console.log(arg);
}
hello(world.msg());
// world.js
function world() {
return 'hello world new';
}
export default { // ES6
msg : world
};
# 把hello.js -打包-> hello.bundle.js
$ webpack hello.js hello.bundle.js
// hello.js
// css-loader处理.css文件
// 然后style-loader插入到head的<style></style>
// index.html中F12可以查看
// !为分隔符, 从路径中源从右向左经过loader
require('style-loader!css-loader!./style.css');
//方法二:
// hello.js
require('./style.css') // loader加载器在命令行中引用
# cli中
# 查看webpack命令行参数
$ webpack -h
# --module-bind参数指的loader
$ webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader' --watch --progress --display-modules --display-reasons
# --watch自动打包, 但还需要主动F5刷新
# --progress 打包进度
# --display-modules 显示打包模块
# --display-reasons 显示打包原因
$ mkdir webpack-demo
$ cd webpack-demo
$ npm init -y
$ yarn add webpack -D
$ mkdir src
$ mkdir dist
$ touch index.html
$ touch webpack.config.js
$ touch webpack.mul.config.js
$ cd src
$ mkdir script // 源文件可能为js,JSX, ES6, CoffeeJS
$ mkdir style // 源文件可能为css,less,sass
$ cd ./dist
$ mkdir css
$ mkdir js
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
const path = require('path'); // node API
module.exports = { // node的CommonJs模块规范
entry: './src/script/main.js', // 入口
output: { // 出口
path: path.resolve(__dirname, 'dist'), // node中方法
// path: __dirname + '/dist/js' // 等价写法
// path: './dist/js' // erro: 必须写绝对路径
filename: 'bundle.js'
},
module: { // loader
rules: [
{test: /\.(js|jsx)$/, use: 'babel-loader'}
]
},
plugins: [ // 插件
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({template: './src/index.html'})
]
};
# webpack.config.js是默认配置文件
$ webpack
# --config运行自定义配置文件
$ webpack --config webapck.dev.config.js
# 写在package.js的scripts中
"scripts": {
"webpack":"webpack --config webpack.dev.config.js --progress --display-modules --colors --display-reasons"
}
$ npm run webpack
entry: 如果传入一个字符串或字符串数组,chunk 会被命名为 main。如果传入一个对象,则每个键(key)会是 chunk 的名称,该值描述了 chunk 的入口起点
output:
// webpack.config.js
const path = require('path'); // node API
module.exports = {
entry : './src/script/main.js',
output : {
path: path.resolve(__dirname,'dist/js'), // 有二种写法
filename:'bundle.js'
}
}
对比发现main.js和vendors.js的runtime是重复的
适合多页面应用程序中,如PC端
output中的[chunkhash]非常有用, 用于上线的缓存问题
// webpack.config.js
const path = require('path'); // node API
module.exports = {
entry : { // 多个chunks
main : './src/script/main.js',
vendors: './src/script/vendors.js'
},
output : {
path: path.resolve(__dirname,'dist/js'), // 有二种写法
filename:'[name].js'
// 占位符(模板字符串):
// [name] 对应entry中的key (chunk name)
// [hash] 模块标识符(module identifier)的 hash, 打包一次变一次
// [chunkhash] 对应文件的md5值, 文件改变chunkhash才变
}
}
const path = require('path');
module.exports = {
// page1.js和page.js之间并列, 彼此没有依赖关系
// bundle.js中有multi模块处理,把page1,2合并
entry : ['./src/script/page1.js', './src/script/page2.js'],
output : {
path : path.resolve(__dirname,'dist/js'),
filename : 'bundle.js',
}
}
html-webpack-plugin
可以自动生成index.html,可压缩,去注释等
插件都是构造函数, 用时需要实例化
html-webpack-plugin
输出index.html的路径参考output
该插件可以指定参考模板
# 安装
$ yarn add html-webpack-plugin -D
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry:{ // 多入口情况, 对应MPA(多页应用),多个chunks
main : './src/script/main.js',
vendors: './src/script/vendors.js'
},
output: {
filename: '[name]-[chunkhash].js', // 可以使用相对路径
path: path.resolve(__dirname, 'dist/js') // 路径对插件也有影响
},
plugins:[
// new HtmlWebpackPlugin() // 默认情况
new HtmlWebpackPlugin({
filename: '../index.html', // 在这里更改相对路径
template:'index.html',
// inject:'head' // js插到head中
title:'Webpack is awesome',
date: new Date()
})
]
};
<%= %>和 <% %>
// index.js (插件参考模板)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- 取值插件中的title设置 -->
<title><%=htmlWebpackPlugin.options.title%></title>
</head>
<body>
<p><%= htmlWebpackPlugin.options.date %></p> // 获取的了date
</body>
</html>
更改成绝对路径
压缩代码
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry:{
main : './src/script/main.js',
vendors: './src/script/vendors.js'
},
output: {
filename: '[name]-[chunkhash].js',
path: path.resolve(__dirname, 'dist/js'),
publicPath:"http://cdn.example.com/assets/" // 线上发布的绝对路径
},
plugins:[
new HtmlWebpackPlugin({
filename: '../index.html',
template:'index.html',
minify:{ // 配置压缩对象参数
collapseWhitespace:true,
removeComments:true
}
})
]
};
// 命令行中: webpack --config webpack.mul.config.js
new HtmlWebpackPlugin()对应一个新的html页面
通过chunks和excludeChunks参数控制引入脚本
需求: 部分chunk以内部script写在head标签中
html-webpack-inline-source-plugin
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry:{
main : './src/script/main.js',
a:'./src/script/a.js',
b:'./src/script/b.js',
c:'./src/script/c.js'
},
output:{
path:path.resolve(__dirname,'dist/js'),
filename:'[name]-[chunkhash].js',
// publicPath:'http://cdn.com'
},
plugins:[
new HtmlWebpackPlugin({
filename:'../a.html',
template:'index.html',
title:'A page',
// chunks:['main','a'], // 引入chunk
excludeChunks:['b','c'] // 排除的chunk
}),
new HtmlWebpackPlugin({
filename:'../b.html',
template:'index.html',
title:'B page',
// chunks:['main','b']
excludeChunks:['a','c']
}),
new HtmlWebpackPlugin({
filename:'../c.html',
template:'index.html',
title:'C page',
chunks:['main','c']
})
]
}
// 演示目录结构
src---componets
|
|---layer
layer.html
layer.js
layer.less
app.js
loader 用于对模块的源代码进行转换。loader 可以使你在 require() 或"加载"模块时预处理文件
使用方法
1. 在webpack.config.js中配置module.rules
2. 在 require 语句中显示使用
3. 同过CLI
// 1.webpack.config.js中配置
// 三种写法等价
module.exports = {
module: {
rules: [
{test: /\.css$/, loader: 'style-loader!css-loader'} // v1.0写法
// or equivalently
{test: /\.css$/, use: ['style-loader','css-loader']} // 推荐
// or equivalently
{test: /\.css$/, use: [
{
loader:'style-loader',
options: {}
},
{ // 推荐
loader: 'css-loader',
options: {}
}
}
]
}
};
// 举例
// use的执行顺序是从右往左从下到上
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: 'style-loader'},
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
}
// 2. 在 require 语句中显示使用
require('style-loader!css-loader?modules!./styles.css');
# 3. 同过CLI
$ webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
Babel官网
webpack Babel-loader API
# 安装
$ yarn add babel-loader babel-core babel-preset-env babel-preset-stage-2 -D
// webpack.config.js
module: {
rules: [
{
test: /\.js$/,
exclude:path.resolve(__dirname, 'node_modules'), // 排除范围
include: path.resolve(__dirname, 'src'),, // 限定范围,注意是绝对路径
use: {
loader: 'babel-loader'
}
}
]
}
// .babelrc
{
"presets": [
"env",
"stage-2"
],
"plugins": []
}
# 安装
$ yarn add style-loader css-loader -D
// webpack.config.js
module:{
rules:[
{
test:/\.css$/,
use:[ 'style-loader', 'css-loader' ]
}
]
}
配合相关插件完成自动添加前缀,
webpack postcss-loader API
postcss-loader
browserslist string (autoprefixer配置用)
# 安装
$ yarn add postcss-loader autoprefixer -D
module : {
rules : [
{
test:/\.css$/,
use:[
'style-loader',
{
loader: 'css-loader',
options: { importLoaders: 1 }
},
'postcss-loader'
]
}
]
}
// postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')({browsers: ['last 4 version']})
]
}