[关闭]
@GivenCui 2017-06-14T16:19:23.000000Z 字数 7663 阅读 801

webpack深入浅出和实战

webpack


网站

webpack-CN

webpack介绍

a) js的模块打包(module bundler)工具, Code Splitting代码分割,实现按需加载,也可以加载各种资源(loader)
b) 兼容AMD,CommonJS(Node),ES6模块语法
c) 部分自动化任务,如热更新, 压缩等

核心概念

入口(entry)
输出(output)
loader
插件(plugins)

webpack安装和命令行

安装

  1. # 当前目录右键打开git-bash
  2. $ mkdir webpack-test
  3. $ cd webpack-test
  4. $ npm init -y
  5. $ npm install webpack --save-dev / yarn add webpack -D/--dev
  6. # 用atom编辑器打开当前目录
  7. $ atom ./

命令行打包

  1. /* Node的CommonJS模式 */
  2. // hello.js
  3. var world = require('./world');
  4. function hello () {
  5. }
  6. // world.js
  7. function world (){
  8. }
  9. module.exports = world;
  1. /* ES6的module模式 不用安装babel也支持 */
  2. // hello.js
  3. import world from './world'; // ES6
  4. function hello(arg) {
  5. console.log(arg);
  6. }
  7. hello(world.msg());
  8. // world.js
  9. function world() {
  10. return 'hello world new';
  11. }
  12. export default { // ES6
  13. msg : world
  14. };
  1. # 把hello.js -打包-> hello.bundle.js
  2. $ webpack hello.js hello.bundle.js

命令行处理css

  1. // hello.js
  2. // css-loader处理.css文件
  3. // 然后style-loader插入到head的<style></style>
  4. // index.html中F12可以查看
  5. // !为分隔符, 从路径中源从右向左经过loader
  6. require('style-loader!css-loader!./style.css');
  7. //方法二:
  8. // hello.js
  9. require('./style.css') // loader加载器在命令行中引用
  10. # cli中
  11. # 查看webpack命令行参数
  12. $ webpack -h
  13. # --module-bind参数指的loader
  14. $ webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader' --watch --progress --display-modules --display-reasons
  15. # --watch自动打包, 但还需要主动F5刷新
  16. # --progress 打包进度
  17. # --display-modules 显示打包模块
  18. # --display-reasons 显示打包原因

webpack基本配置

目录结构搭建

  1. $ mkdir webpack-demo
  2. $ cd webpack-demo
  3. $ npm init -y
  4. $ yarn add webpack -D
  5. $ mkdir src
  6. $ mkdir dist
  7. $ touch index.html
  8. $ touch webpack.config.js
  9. $ touch webpack.mul.config.js
  10. $ cd src
  11. $ mkdir script // 源文件可能为js,JSX, ES6, CoffeeJS
  12. $ mkdir style // 源文件可能为css,less,sass
  13. $ cd ./dist
  14. $ mkdir css
  15. $ mkdir js

webpack的配置文件

webpack.config.js

  1. // webpack.config.js
  2. const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
  3. const webpack = require('webpack'); //to access built-in plugins
  4. const path = require('path'); // node API
  5. module.exports = { // node的CommonJs模块规范
  6. entry: './src/script/main.js', // 入口
  7. output: { // 出口
  8. path: path.resolve(__dirname, 'dist'), // node中方法
  9. // path: __dirname + '/dist/js' // 等价写法
  10. // path: './dist/js' // erro: 必须写绝对路径
  11. filename: 'bundle.js'
  12. },
  13. module: { // loader
  14. rules: [
  15. {test: /\.(js|jsx)$/, use: 'babel-loader'}
  16. ]
  17. },
  18. plugins: [ // 插件
  19. new webpack.optimize.UglifyJsPlugin(),
  20. new HtmlWebpackPlugin({template: './src/index.html'})
  21. ]
  22. };

以webpack.config.js配置运行

  1. # webpack.config.js是默认配置文件
  2. $ webpack
  3. # --config运行自定义配置文件
  4. $ webpack --config webapck.dev.config.js
  5. # 写在package.js的scripts中
  6. "scripts": {
  7. "webpack":"webpack --config webpack.dev.config.js --progress --display-modules --colors --display-reasons"
  8. }
  9. $ npm run webpack

配置文件的entry和output

单入口配置

entry: 如果传入一个字符串或字符串数组,chunk 会被命名为 main。如果传入一个对象,则每个键(key)会是 chunk 的名称,该值描述了 chunk 的入口起点

output:

  1. // webpack.config.js
  2. const path = require('path'); // node API
  3. module.exports = {
  4. entry : './src/script/main.js',
  5. output : {
  6. path: path.resolve(__dirname,'dist/js'), // 有二种写法
  7. filename:'bundle.js'
  8. }
  9. }

多入口配置

对比发现main.js和vendors.js的runtime是重复的
适合多页面应用程序中,如PC端
output中的[chunkhash]非常有用, 用于上线的缓存问题

  1. // webpack.config.js
  2. const path = require('path'); // node API
  3. module.exports = {
  4. entry : { // 多个chunks
  5. main : './src/script/main.js',
  6. vendors: './src/script/vendors.js'
  7. },
  8. output : {
  9. path: path.resolve(__dirname,'dist/js'), // 有二种写法
  10. filename:'[name].js'
  11. // 占位符(模板字符串):
  12. // [name] 对应entry中的key (chunk name)
  13. // [hash] 模块标识符(module identifier)的 hash, 打包一次变一次
  14. // [chunkhash] 对应文件的md5值, 文件改变chunkhash才变
  15. }
  16. }
  1. const path = require('path');
  2. module.exports = {
  3. // page1.js和page.js之间并列, 彼此没有依赖关系
  4. // bundle.js中有multi模块处理,把page1,2合并
  5. entry : ['./src/script/page1.js', './src/script/page2.js'],
  6. output : {
  7. path : path.resolve(__dirname,'dist/js'),
  8. filename : 'bundle.js',
  9. }
  10. }

生成项目中的html页面(插件)

html-webpack-plugin

html-webpack-plugin可以自动生成index.html,可压缩,去注释等
插件都是构造函数, 用时需要实例化

html-webpack-plugin输出index.html的路径参考output
该插件可以指定参考模板

安装和使用

  1. # 安装
  2. $ yarn add html-webpack-plugin -D
  3. // webpack.config.js
  4. const path = require('path');
  5. const HtmlWebpackPlugin = require('html-webpack-plugin');
  6. module.exports = {
  7. entry:{ // 多入口情况, 对应MPA(多页应用),多个chunks
  8. main : './src/script/main.js',
  9. vendors: './src/script/vendors.js'
  10. },
  11. output: {
  12. filename: '[name]-[chunkhash].js', // 可以使用相对路径
  13. path: path.resolve(__dirname, 'dist/js') // 路径对插件也有影响
  14. },
  15. plugins:[
  16. // new HtmlWebpackPlugin() // 默认情况
  17. new HtmlWebpackPlugin({
  18. filename: '../index.html', // 在这里更改相对路径
  19. template:'index.html',
  20. // inject:'head' // js插到head中
  21. title:'Webpack is awesome',
  22. date: new Date()
  23. })
  24. ]
  25. };

模板支持ejs, <%= %>和 <% %>

  1. // index.js (插件参考模板)
  2. <!DOCTYPE html>
  3. <html lang="zh-CN">
  4. <head>
  5. <meta charset="UTF-8">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <!-- 取值插件中的title设置 -->
  9. <title><%=htmlWebpackPlugin.options.title%></title>
  10. </head>
  11. <body>
  12. <p><%= htmlWebpackPlugin.options.date %></p> // 获取的了date
  13. </body>
  14. </html>

上线配置

更改成绝对路径
压缩代码

  1. const path = require('path');
  2. const HtmlWebpackPlugin = require('html-webpack-plugin');
  3. module.exports = {
  4. entry:{
  5. main : './src/script/main.js',
  6. vendors: './src/script/vendors.js'
  7. },
  8. output: {
  9. filename: '[name]-[chunkhash].js',
  10. path: path.resolve(__dirname, 'dist/js'),
  11. publicPath:"http://cdn.example.com/assets/" // 线上发布的绝对路径
  12. },
  13. plugins:[
  14. new HtmlWebpackPlugin({
  15. filename: '../index.html',
  16. template:'index.html',
  17. minify:{ // 配置压缩对象参数
  18. collapseWhitespace:true,
  19. removeComments:true
  20. }
  21. })
  22. ]
  23. };
  24. // 命令行中: webpack --config webpack.mul.config.js

多页面配置

new HtmlWebpackPlugin()对应一个新的html页面
通过chunks和excludeChunks参数控制引入脚本

需求: 部分chunk以内部script写在head标签中
html-webpack-inline-source-plugin

  1. const path = require('path');
  2. const HtmlWebpackPlugin = require('html-webpack-plugin');
  3. module.exports = {
  4. entry:{
  5. main : './src/script/main.js',
  6. a:'./src/script/a.js',
  7. b:'./src/script/b.js',
  8. c:'./src/script/c.js'
  9. },
  10. output:{
  11. path:path.resolve(__dirname,'dist/js'),
  12. filename:'[name]-[chunkhash].js',
  13. // publicPath:'http://cdn.com'
  14. },
  15. plugins:[
  16. new HtmlWebpackPlugin({
  17. filename:'../a.html',
  18. template:'index.html',
  19. title:'A page',
  20. // chunks:['main','a'], // 引入chunk
  21. excludeChunks:['b','c'] // 排除的chunk
  22. }),
  23. new HtmlWebpackPlugin({
  24. filename:'../b.html',
  25. template:'index.html',
  26. title:'B page',
  27. // chunks:['main','b']
  28. excludeChunks:['a','c']
  29. }),
  30. new HtmlWebpackPlugin({
  31. filename:'../c.html',
  32. template:'index.html',
  33. title:'C page',
  34. chunks:['main','c']
  35. })
  36. ]
  37. }

处理项目中的资源文件

  1. // 演示目录结构
  2. src---componets
  3. |
  4. |---layer
  5. layer.html
  6. layer.js
  7. layer.less
  8. app.js

什么是loader

loader 用于对模块的源代码进行转换。loader 可以使你在 require() 或"加载"模块时预处理文件

使用方法
1. 在webpack.config.js中配置module.rules
2. 在 require 语句中显示使用
3. 同过CLI

  1. // 1.webpack.config.js中配置
  2. // 三种写法等价
  3. module.exports = {
  4. module: {
  5. rules: [
  6. {test: /\.css$/, loader: 'style-loader!css-loader'} // v1.0写法
  7. // or equivalently
  8. {test: /\.css$/, use: ['style-loader','css-loader']} // 推荐
  9. // or equivalently
  10. {test: /\.css$/, use: [
  11. {
  12. loader:'style-loader',
  13. options: {}
  14. },
  15. { // 推荐
  16. loader: 'css-loader',
  17. options: {}
  18. }
  19. }
  20. ]
  21. }
  22. };
  23. // 举例
  24. // use的执行顺序是从右往左从下到上
  25. module: {
  26. rules: [
  27. {
  28. test: /\.css$/,
  29. use: [
  30. { loader: 'style-loader'},
  31. {
  32. loader: 'css-loader',
  33. options: {
  34. modules: true
  35. }
  36. }
  37. ]
  38. }
  39. ]
  40. }
  41. // 2. 在 require 语句中显示使用
  42. require('style-loader!css-loader?modules!./styles.css');
  43. # 3. 同过CLI
  44. $ webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'

babel-loader

Babel官网
webpack Babel-loader API

  1. # 安装
  2. $ yarn add babel-loader babel-core babel-preset-env babel-preset-stage-2 -D
  3. // webpack.config.js
  4. module: {
  5. rules: [
  6. {
  7. test: /\.js$/,
  8. exclude:path.resolve(__dirname, 'node_modules'), // 排除范围
  9. include: path.resolve(__dirname, 'src'),, // 限定范围,注意是绝对路径
  10. use: {
  11. loader: 'babel-loader'
  12. }
  13. }
  14. ]
  15. }
  16. // .babelrc
  17. {
  18. "presets": [
  19. "env",
  20. "stage-2"
  21. ],
  22. "plugins": []
  23. }

处理css

style-loader,css-loader

  1. # 安装
  2. $ yarn add style-loader css-loader -D
  3. // webpack.config.js
  4. module:{
  5. rules:[
  6. {
  7. test:/\.css$/,
  8. use:[ 'style-loader', 'css-loader' ]
  9. }
  10. ]
  11. }

postcss-loader

配合相关插件完成自动添加前缀,

webpack postcss-loader API
postcss-loader
browserslist string (autoprefixer配置用)

  1. # 安装
  2. $ yarn add postcss-loader autoprefixer -D
  3. module : {
  4. rules : [
  5. {
  6. test:/\.css$/,
  7. use:[
  8. 'style-loader',
  9. {
  10. loader: 'css-loader',
  11. options: { importLoaders: 1 }
  12. },
  13. 'postcss-loader'
  14. ]
  15. }
  16. ]
  17. }
  1. // postcss.config.js
  2. module.exports = {
  3. plugins: [
  4. require('autoprefixer')({browsers: ['last 4 version']})
  5. ]
  6. }

处理less和sass

处理模板文件

处理图片和其它文件

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注