webpack

本文详细介绍了webpack的基本概念、安装与命令,包括代码分割、模块打包、loader的使用等。接着深入讲解了webpack配置文件的创建,特别是entry和output的设置。此外,文章还演示了如何使用html-webpack-plugin自动化生成项目中的HTML文件,并处理资源文件,如CSS、图片、模板文件和其他静态资产。最后,探讨了如何使用loader转换ES6代码、处理CSS、Less和Sass,以及处理模板文件和图片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、webpack基本介绍

  • **1-1**webpack基本介绍
    webpack的概念和作用
    模块打包器
    代码分割
    代码文件打包
    loader加载
    commonjs规范
    模块热更新
    适用于大型项目

  • **1-2**webpack安装和命令
    安装
    npm install webpack --save-dev

例子:
新建hello.js执行命令 webpack hello.js hello.bundle.js ,会生成hello.bundle.js文件,观察文件中的内容,可以看到webpack在文件中生成了许多其他代码

新建world.js并在hello.js文件中require('./world.js'),再执行命令webpack hello.js hello.bundle.js,观察hello.bundle.js文件中的内容

新建style.css,在样式表中随便新建几行样式html,body{background: #f00;},在hello.js文件中require('style-loader!css-loader!./style.css'),执行命令webpack hello.js hello.bundle.js(注意:webpack加载css需要用到css-loader,行内样式需要用到style-loader。安装loader npm install css-loader style-loader --save-dev)
css-loader用来将style.css打包到hello.bundle.js文件中,使webpack能处理.css文件,如果将css-loader处理后的文件,引入到页面中后(在这个例子中引入页面的是hello.bundle.js),style-loader则会将style.css中的样式以<style></style>的形式插入到head

如果在页面中没有加载这两个loader也可以在命令行中直接加载loader webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader'

输入webpack可以查看webpack中有哪些配置项
webpack hello.js hello.bundle.js --watch 用来监听文件,如果文件有变化则自动编译打包
webpack hello.js hello.bundle.js --progress 用来查看打包的进度
webpack hello.js hello.bundle.js --display-module 用来查看打包的模块
webpack hello.js hello.bundle.js --display-reson 用来查看打包的原因

二、webpack基本配置

  • 2-1建立项目的webpack配置

例子:
在webpack-demo目录下新建以下文件

webpack-demo
-dist
--js
-src
--script
--style
-index.html
-package.json
-webpack.config.js

webpack.config.js

module.exports = {
    entry: './src/script/main.js',//入口文件
    output: {
        path: './dist/js',//输出路径
        filename: 'bundle.js'//输出文件名
    }
}

运行 webpack 会在dist下的js目录下生成bundle.js

可在pack.json的script字段中添加配置webpack

"scripts": {
    "webpack":"webpack --config webpack.config.js --progress --display-modules --colors --display-reasons"
},
  • 2-2webpack配置的entryoutput
    entry是入口文件
    entry可以是一个数组

    entry:[‘a.js’,’main.js’]

entry可以是一个对象用于多入口的情况下

entry:{
    page1:'./page1'
    page2:['entry1.js','entry2.js']
}

entry是多入口的情况下,output也应该是多个输出 filename有三个可选参数 [name][hash][chunkhash]

output: {
    path: _dirname+'/built',//输出路径
    filename: '[name].js'//输出文件名
}

注意,在不同的版本下可能会报路径不是绝对路径的错误,解决办法为

var path = require('path');
module.exports = {
    entry: [url('src/script/main.js'), url('src/script/a.js')],
    output: {
        path: url('./dist/js/'),
        filename: 'bundle.js'
    }
}
function url(url) {
    return path.resolve(__dirname, url)
}

三、生成项目中的html文件

  • 3-1自动化生成项目中的html文件(上)

安装
html-webpack-plugin(这里有个坑就是,如果在全局安装webpack,在运行npm run webpack之前需要运行 npm link webpack)
自动生成html的意义在于,html中引用的js文件好多都是webpack打包之后生成的,生成的文件名和目录都有可能改变,这个时候不能手动来修改每一个变动的路径,太耗时,这个时候就要通过html-webpack-plugins这个插件来自动在html中生成对js的引用

在webpack.config.js中加入plugins配置项

var htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry: {
        main: './src/script/main.js',
        a: './src/script/a.js'
    },
    output: {
        path: './dist',
        filename: 'js/[name]-[hash].js'
    },
    plugins: [
        new htmlWebpackPlugin({
            template:'index.html',
            inject:'head'
        })
    ]
}

在htmlWebpackPlugin插件中配置项template用来定义引用的模板文件,inject用来指定脚本在dom文档中的插入位置

  • 3-2自动化生成项目中的html文件(中)

template应用场景
在参数中传参,在模板中引用

plugins: [
    new htmlWebpackPlugin({
        template:'index.html',
        inject:'head',
        title:'webpack is good'
    })
]

在html的title中,以如下的方式引用

<title><%= htmlWebpackPlugin.options.plugins.title %></title>

<%= htmlWebpackPlugin.options.title %>这种方式的引用在模板中的任何一个位置都可以,例如

plugins: [
    new htmlWebpackPlugin({
        template:'index.html',
        inject:'head',
        title:'webpack is good'
        date:new Date()
    })
]
<body>
    <%= htmlWebpackPlugin.options.date %>
</body>

这样在编译后的index.html文件中会包含日期信息Tue Apr 04 2017 23:25:58 GMT+0800 (中国标准时间)

在html文件中body标签中,输入如下代码,运行 npm run webpack

    <% for(var key in htmlWebpackPlugin){ %>
    <%= key %>
    <% } %>

生成的文件中会有files options,这两个值说明在htmlWebpackPlugin插件中存在这两个对象

继续遍历htmlWebpackPlugin.files htmlWebpackPlugin.options这两个对象

    <% for(var key in htmlWebpackPlugin.files){ %>
    <%= key %>:<%= JSON.stringify(htmlWebpackPlugin.files[key])%>
    <% } %>
    <% for(var key in htmlWebpackPlugin.options){ %>
    <%= key %>:<%= JSON.stringify(htmlWebpackPlugin.options[key])%>
    <% } %>

得到

    //files
    publicPath:""
    chunks:{"main":{"size":27,"entry":"js/main-c6074c5f07c44041cf45.js","hash":"ddd0a31267a8793ca2d8","css":[]},"a":{"size":14,"entry":"js/a-c6074c5f07c44041cf45.js","hash":"ef609b383ce569e49d38","css":[]}}
    js:["js/main-c6074c5f07c44041cf45.js","js/a-c6074c5f07c44041cf45.js"]
    css:[]
    manifest:
    //options
    template:"F:\\localhost\\wamp\\www\\webpack-demo\\node_modules\\._html-webpack-plugin@2.28.0@html-webpack-plugin\\lib\\loader.js!F:\\localhost\\wamp\\www\\webpack-demo\\index.html"
    filename:"index.html"    
    hash:false   
    inject:"head"    
    compile:true    
    favicon:false    
    minify:false    
    cache:true   
    showErrors:true   
    chunks:"all"   
    excludeChunks:[]   
    title:"webpack is good"  
    xhtml:false
    date:"2017-04-04T15:45:55.712Z"
//压缩
minify:{
    removeComments:true,//删除注释
    collapseWhitespace:true//删除空格
}

可以用<%= %>这种灵活的方式实现更多的个性化定制

  • 3-3自动化生成项目中的html文件(下)

多文件形式

var 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: './dist',
        filename: 'js/[name]-[hash].js'
    },
    plugins: [
        new htmlWebpackPlugin({
            filename:'main.html',
            template: 'index.html',
            title: 'webpack is main',
            date: new Date()
        }),
        new htmlWebpackPlugin({
            filename:'a.html',
            template: 'index.html',
            title: 'webpack is a',
            date: new Date()
        }),
        new htmlWebpackPlugin({
            filename:'b.html',
            template: 'index.html',
            title: 'webpack is b',
            date: new Date()
        }),
        new htmlWebpackPlugin({
            filename:'c.html',
            template: 'index.html',
            title: 'webpack is c',
            date: new Date()
        })
    ]
}

chunks用来指定匹配的生成文件中应该生成数组中的文件(excludeChunks和chunks相反)

var 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: './dist',
        filename: 'js/[name]-[hash].js'
    },
    plugins: [
        new htmlWebpackPlugin({
            filename:'main.html',
            template: 'index.html',
            title: 'webpack is main',
            date: new Date(),
            chunks:['a','b','c']
        }),
        new htmlWebpackPlugin({
            filename:'a.html',
            template: 'index.html',
            title: 'webpack is a',
            date: new Date(),
            chunks:['b','c']
        }),
        new htmlWebpackPlugin({
            filename:'b.html',
            template: 'index.html',
            title: 'webpack is b',
            date: new Date(),
            chunks:['a','c']
        }),
        new htmlWebpackPlugin({
            filename:'c.html',
            template: 'index.html',
            title: 'webpack is c',
            date: new Date(),
            chunks:['a','b']
        })
    ]
}

main.html中会生成 a.js b.js c.js
a.html中会生成b.js c.js
b.html中会生成a.js c.js
c.html中会生成a.js b.js

将生成的脚本变成内联脚本

compilation.assets[htmlWebpackPlugin.files.chunks.main.entry].source()

如果在申明publicPath的情况下代码应该是这样

compilation.assets[htmlWebpackPlugin.files.chunks.main.entry.substr(htmlWebpackPlugin.files.publicPath.length)].source()

htmlWebpackPlugin.files.publicPath.length 得到publicPath的长度例如 https://www.baidu.com
htmlWebpackPlugin.files.chunks.main.entry.substr()得到文件真实路径
最后用compilation.assets[].source()得到内容
在main.js已经以内联的方式插入到文档,那么多后续的出来main.js则不需要任何操作,可以在index.html里面写入这样的模板语法,来判断是否是main.js以外的文件,如果不是则插入

四、处理项目中的资源文件

  • 4-1什么是loader以及loader的特性

  • 4-2使用babel-loader转换ES6代码

webpack-demo
-dist
-node_modules
-src
--components
---layer
----layer.html
----layer.js
----layer.css
--app.js
-index.html
-package.json
-webpack.config.js
module:{
    loaders:[
        {
            test:'/\.js$/',
            loader:'babel',
            exclude:'./node_modules/',//提高打包速度
            include:'./src/',//提高打包速度
            query:{
                presets:['latest']
            }
        }
    ]
}

query用来指定额外的参数。presets:[‘latest’]用来指定babel将要处理js的版本,版本可能有如下几种或者更多中情况ES2015 ES2016 ES2017,latest指定最近的三个版本
presets:[‘latest’]也可以放在package.json文件中

"babel":{
    "presets":["latest"]
}

或者放在.babelrc中

{
    presets:["latest"]
}

path.resolve(__dirname+”),用来将相对路径改为绝对路径

cnpm install –save-dev babel-preset-latest
cnpm install –save-dev babel

注意:在webpack2.0中 有些不一样
npm install –save-dev babel-loader babel-core babel-preset-env

module: {
    rules: [
        {
            test:  /\.js$/,
            loader: 'babel-loader',
            exclude:  path.resolve(__dirname + 'node_modules'),
            include: path.resolve(__dirname + 'src'),
            query: {
                presets: ['env']
            }
        }
    ]
}

注意:加入include配置项会导致babel不处理es6语法,原因暂不明

  • 4-3处理项目中的css

postcss-loader
autoprefixer
autoprefixer是postcss-loader的一个子集

module: {
    rules: [{
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: path.resolve(__dirname + 'node_modules'),
            query: {
                presets: ['env']
            }
        },
        {
            test: /\.css$/,
            use: [
                'style-loader',
                'css-loader?importLoaders=1',
                {
                    loader: 'postcss-loader',
                    options: {
                        plugins: function() {
                            return [
                                require('autoprefixer')
                            ];
                        }
                    }
                }
            ]
        }
    ]
}

loader的执行顺序从右向左
?importLoaders=1!是css-loader这个loader后面的参数,意思是在postcss-loader后制定一个处理import样式的命令

  • 4-4使用less和sass
    sass-loader less-loader

  • 4-5处理模板文件
    html-loader

  • 4-6处理图片及其他文件
    file-loader url-loader

var htmlWebpackPlugin = require('html-webpack-plugin');

var path = require('path');
module.exports = {
    entry: {
        "main": __dirname + '/src/script/main.js',
        "a": __dirname + '/src/script/a.js',
        "b": __dirname + '/src/script/b.js',
        "c": __dirname + '/src/script/c.js',
    },
    output: {
        filename: 'js/[name]-[hash].js',
        path: __dirname + '/dist',
    },
    module: {
        rules: [{
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: path.resolve(__dirname + 'node_modules'),
                query: {
                    presets: ['env']
                }
            },
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    {
                        loader:'css-loader',
                        options:{
                           importLoaders:1
                         }
                    },
                    {
                        loader: 'postcss-loader',
                        options: {
                            plugins: function() {
                                return [
                                    require('autoprefixer')
                                ];
                            }
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new htmlWebpackPlugin({
            filename: 'main.html',
            template: 'index.html',
            inject: false,
            title: 'webpack is main.html',
            date: new Date(),
            excludeChunks: ['a', 'b']
        }),
        new htmlWebpackPlugin({
            filename: 'a.html',
            template: 'index.html',
            inject: false,
            title: 'webpack is a.html',
            date: new Date(),
            excludeChunks: ['b', 'c']
        }),
        new htmlWebpackPlugin({
            filename: 'b.html',
            template: 'index.html',
            inject: false,
            title: 'webpack is b.html',
            date: new Date(),
            excludeChunks: ['a', 'c']
        }),
        new htmlWebpackPlugin({
            filename: 'c.html',
            template: 'index.html',
            inject: false,
            title: 'webpack is c.html',
            date: new Date(),
            excludeChunks: ['a', 'b']
        })
    ]
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值