欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

webpack配置

程序员文章站 2022-07-02 23:35:45
...

文章中以 $ 符号开头的是在终端输入的命令 
文章中以 vim 开头为编辑文件内容

从零开始

$ mkdir dailypaper
新建一个项目文件夹dailypaper
$ npm init
    在该文件夹下npm init初始化项目文件夹会产生package.json文件
$ npm install -D webpack    
    本地局域安装webpack依赖
$ npm install -D webpack-dev-server   
     开发环境安装服务器热更新依赖
$ mkdir app        
    创建app文件夹用来存放放原始代码文件
$ mkdir public      
     创建public文件夹用来存放打包后的文件
$ touch webpack.config.js    
    创建web pack.config.js 配置文件

webpack.config.js配置文件四大重要组成部分:入口文件、出口文件、loader、插件plugins

vim web pack.config.js 初始化webpack.config.js的内容

var config = {

};
module.exports = config;

这里的module.exports = config;相当于export default config;。由于目前还没有安装支持ES6的编译插件,因此不能直接用ES6的语法,否则会报错。

vim package.json 的scripts里添加快速启动热更新服务的脚本

{
    //…
    "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --open --config webpack.config.js",
    },
    //…
}

当运行 npm run dev时,就会执行”webpack-dev-server –open –config webpack.config.js”命令,其中—config 是指向 webpack-dev-server 读取的配置文件路径,即之前创建的 webpack.config.js 文件。—open会在执行命令时自动在浏览器打开页面,默认地址为127.0.0.1:8080,不过IP和端口都是可以配置的,如:

vim package.json

 "scripts": {
    "dev": "webpack-dev-server —-host 172.172.172.1 —-port 8888 —-open --config webpack.config.js",
    },

一般在局域网中,需要其他同事访问时可以这样设置,否则默认就可以

入口出口配置

Webpack配置 最重要的是两项配置入口(Entry)和出口(Output),在dailypaper文件夹下新建一个空的app.js作为入口的文件,再进行

在dailypaper文件下

$ touch app.js
    新建app.js文件   

vim web pack.config.js中

var path = require('path');
var config = {
    entry: {
        app: './app.js'
    },
    output: {
        path: path.join(__dirname,'./public'),
        publicPath: '/public/',
        filename: 'main.js',
    },

};
module.exports = config;

entry中的main是单入口,webpack会从main.js文件开始工作, output中path选项用来存放打包后的文件输出目录,是必填项。 publicPath指定资源文件引用的目录,如果你的资源文件放在CDN上,可填CDN的网址。filename用于指定输出文件的名称。因此,这里配置的output意为打包后的文件会存储为daily/public/main.js文件,只要在html中引入它就可以了。

在dailypaper文件下

$ touch index.html
    新建index.html文件
  • vim index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>dailypaper</title>
</head>
<body>
    <div id="app">
        Hello World
    </div>
    <script src="./public/main.js"></script>
</body>
</html>

然后就可以执行以下命令了:

$ npm run dev    
    就能打开网页显示Hello World了

vim app.js 打开dailypaper文件夹下的app.js,添加一行代码

document.getElementById('app').innerHTML = 'Hello webpack.';

此时页面已经自动变成了Hello webpack. 
此时看浏览器开发者工具的network视图中(刷新页面)的main.js有几千行代码,这是在开发环境下,大多都是webpack-dev-server的功能,只在开发时有效,在生产环境下编译就不会这么臃肿,执行以下命令打包

$ webpack —progress —hide-modules    打包 没有压缩

这时public 下的main.js就只有几十行

loader配置

webpack配置除了入口和出口,需要进一步配置来实现更强大的功能 
每个文件都是一个模块,不同的模块需要不同的加载器loaders来处理,加载器是webpack最重要的功能,通过安装不同的加载器可以对各种后缀名的文件进行处理,比如CSS样式需要用到 style-loaderloader和 css-loader

$ install css-loader style-loader -D
安装完成后再在webpack.config.js中配置Loader,增加对css文件的处理

vim web pack.config.js

var path = require('path');
var config = {
    entry: {
        app: './app'
    },
    output: {
        path: path.join(__dirname,'./public'),
        publicPath: '/public/',
        filename: 'main.js'
    },
    module: {
        rules: [
            {
                test:/\.css$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    }

};

module.exports = config;

在 module 对象中的 rules 属性中可以指定一系列的 loaders ,每一个 loader 必须包含 test 和 use 两个选项, 
以上意思是,当遇到后缀名为.css的文件时,先将它通过 css-loader 转换,再通过 style-loader 转换,然后继续打包,use的值可以是字符串或者数组,如果是数组,它的编译顺序是从后往前。

dailypaper文件夹下

$ touch style.css
    新建style.css,并在app.js中导入

vim style.css

#app {
    font-size:24px;
    color:#f50;
}

vim 在app.js中

import './style.css’;    //配置了loader之后,就可以直接这么将样式文件通过import引入js 文件中
document.getElementById('app').innerHTML = 'Hello webpack.';

插件配置

CSS是通过JS动态创建 style 标签来写入的, 这意味着代码已经编译在了main.js中,但在实际业务中,样式文件会很多,都放在JS里太占体积,还不能做缓存。这时候需要用到另一个重要——插件(Plugin) 
这里可以使用一个 extract-text-webpack-plugin 的插件来将散落在各地的CSS提取出来,并生成一个main.css文件,最终在index.html里通过 的形式加载。

$ npm install extract-text-webpack-plugin -D

然后在配置文件中导入插件,并改写loader的配置

vim web pack.config.js

var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var config = {
    entry: {
        app: './app'
    },
    output: {
        path: path.join(__dirname,'./public'),
        publicPath: '/public/',
        filename: 'main.js'
    },
    module: {
        rules: [
            {
                test:/\.css$/,
                // use: [
                //     'style-loader',
                //     'css-loader'
                // ]
                use: ExtractTextPlugin.extract({
                    use: 'css-loader',
                    fallback:'style-loader'
                })
            }
        ]
    },
    plugins:[
        //重命名提取后的CSS文件,此时必须要在index.html中引用才会有样式效果,打包成一个main.css
        new ExtractTextPlugin("main.css")
    ]

};

module.exports = config;

vim Index.html 必须要使用 link 标签来引用才会有样式展示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>dailypaper</title>
    <link rel="stylesheet" type="text-css" href="/public/main.css">
</head>
<body>
    <div id="app">
        Hello World
    </div>
    <script src="/public/main.js"></script>
</body>
</html>

进阶配置

引入 .vue 单文件与Vue-loader

.vue单文件组件需要使用 vue-loader 转换处理 
一个 .vue 文件包括 template script style 三部分

$ touch app.vue
    app 文件夹下 新建 app.vue 

vim app.vue

<template>
    <div> 你好,单文件组件</div>
</template>

<script>
    export default {

    }
</script>

<style scoped >
    div {
        color:red;
    }
</style>

scoped 表示当前的CSS只在当前组件内有效,如果不加,会应用到整个项目,lang=‘less’ 表示使用 less 预编译处理

使用 .vue 文件需要先安装 vue-loader vue-style-loader 等加载器并做配置 
另外要使用ES6语法,需要安装 babel 和 babel-loader 等加载器。

$ npm install -S vue
$ npm install -D vue-loader
$ npm install -D vue-style-loader
$ npm install -D vue-template-compiler
$ npm install -D vue-hot-reload-api
$ npm install -D babel
$ npm install -D babel-loader
$ npm install -D babel-core
$ npm install -D babel-plugin-transform-runtime
$ npm install -D babel-preset-es2015
$ npm install -D babel-runtime

安装完成后,添加配置

vim webpack.config.js 来支持对 .vue 以及 ES6 的解析;

var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var config = {
    entry: {
        app: './app'
    },
    output: {
        path: path.join(__dirname,'./public'),
        publicPath: '/public/',
        filename: 'main.js'
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader:'vue-loader',
                options: {
                    loaders: {
                        css: ExtractTextPlugin.extract({
                            use:'css-loader',
                            fallback:'vue-style-loader'
                        })
                    }
                }
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test:/\.css$/,
                // use: [
                //     'style-loader',
                //     'css-loader'
                // ]
                use: ExtractTextPlugin.extract({
                    use: 'css-loader',
                    fallback:'style-loader'
                })
            }
        ]
    },
    plugins:[
        //重命名提取后的CSS文件
        new ExtractTextPlugin("main.css")
    ]

};

module.exports = config;

vue-loader 在编译 .vue 文件时,会对

// document.getElementById('app').innerHTML = 'Hello webpack.’;

import './style.css';
import App from './app/app.vue';
import Vue from 'vue';

new Vue({
    el: '#app',
    render: h => h(App)    //这里不能直接写为components: { App },template:’<App></App>’,会报错

})

然后就可以

$ npm run dev 在浏览器中可以看到app.vue组件的内容替换了index.html 中的 id =‘app' 的 div

生产环境

进一步配置webpack

安装 url-loader file-loader 来支持图片、字体等文件;

$ npm install url-loader file-loader -D

vim webpack.config.js

var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var config = {
    entry: {
        app: './app'
    },
    output: {
        path: path.join(__dirname,'./public'),
        publicPath: '/public/',
        filename: 'main.js'
    },
    module: {
        rules: [
            {
                test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
                loader: 'url-loader?limit=1024'
            },
            {
                test: /\.vue$/,
                loader:'vue-loader',
                options: {
                    loaders: {
                        css: ExtractTextPlugin.extract({
                            use:'css-loader',
                            fallback:'vue-style-loader'
                        })

                    },

                }
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test:/\.css$/,
                // use: [
                //     'style-loader',
                //     'css-loader'
                // ]
                use: ExtractTextPlugin.extract({
                    use: 'css-loader',
                    fallback:'style-loader'
                })
            }
        ]
    },
    plugins:[
        //重命名提取后的CSS文件
        new ExtractTextPlugin("main.css")
    ]

};

module.exports = config;

当遇到 .gif .png .ttf 等格式文件时,url-loader 会把它们一起编译到 public 目录下, “?limit=1024”是指如果这个文件小于1kb,就以base64 的形式加载,不会生成一个文件。 
在app.vue 中加载一个图片。

vim app.vue

<template>
    <div> 
        <h1>你好,单文件组件</h1>
        <p>
            nice to see you!
        </p>
        <img src="./img/snow.jpg" width="300">
    </div>
</template>

<script>
    export default {
        name:'app',
        data(){
            return {

            }
        }

    }
</script>

<style scoped lang='less'>
    div {
        color:red;
        p {
            color:blue;
        }
    }
</style>

打包上线

打包后的产物: 
单页面富应用(SPA)最终只有一个html 文件,其余都是静态资源,实际部署到生产环境时,一般会将html 挂在后端程序下,由后端路由渲染这个页面,将所有的静态资源(CSS JS、image、iconfont等)单独部署到CDN,当然也可以和后端程序部署在一起,这样就实现了前后端完全分离。 
我们在webpack 的output 选项里已经指定了path 和publicPath ,打完包后,所有的资源都会在dailypaper/public 目录下。

下面是两个打包会用到的依赖, 使用NPM 安装

$ npm install webpack-merge -D
$ npm html-webpack-plugin -D

为了方便开发和生产环境的切换,我们在 dailypaper 目录下再建一个用于生产环境的配置文件 webpack.prod.config.js

vim webpack.prod.config.js

var webpack = require('webpack');
var HtmlwebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var merge = require('webpack-merge');
var webpackBaseConfig = require('./webpack.config.js');

//清空基本配置的插件列表
webpackBaseConfig.plugins=[];

module.exports=merge(webpackBaseConfig,{
    output: {
        publicPath: '/public_CDN/',
        //将入口文件重命名为带有20位hash值的唯一文件
        filename: 'static/js/[name].[hash].js'    //filename定义的路径就在打包配置的public文件夹下
    },
    plugins: [
        new ExtractTextPlugin({
            //提取CSS, 并重命名为带有20位hash值的唯一文件
            filename: 'static/css/[name].[hash].css',
            allChunks: true
        }),
        //定义当前的code 环境为生产环境
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: '"production"'
            }
        }),
        //压缩 JS
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            }
        }),
        //提取模板,并保存入口html文件
        new HtmlwebpackPlugin({
            filename: 'index_prod.html',//在public文件夹下,index_prod.html与static在同一目录下,
            template: './index.ejs',
            inject: false
        })
    ]
})

其中/public_CDN/需要修改为部署存放static文件夹的CDN服务器地址。 
上面安装的web pack-merge 模块就是用于合并两个webpack的配置文件,所以prod的配置是在web pack_config.js的基础上扩展的,静态资源大部分场景下都有缓存(304),更新上线后一般都希望用户能及时地看到内容,所以给打包后的CSS和JS文件的名称都加了20位的hash值,这样文件名就唯一了,只要不对html 设置缓存,上线后就能加载最新的静态资源。 
Html-webpack-plugin 是用来生成 .html 文件的, 它通过 template 选项来读取指定的模板 index.ejs, 然后输出到 filename 指定的目录, 也就是 public/index_prod.html。

下面是模板 index.ejs 动态设置了静态资源的路径和文件名 该文件在dailypaper目录下 
vim index.ejs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>dailypaper</title>
    <link rel="stylesheet" type="text-css" href="<%= htmlWebpackPlugin.files.css[0] %>">
</head>
<body>
    <div id="app">

    </div>
    <script type='text/javascript' src="<%= htmlWebpackPlugin.files.js[0] %>"></script>
</body>
</html>

ejs 是一个JavaScript 模板库,用来从JSON 数据中生成HTML 字符串, 常用语Node.js

vim webpack.config.js

var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var config = {
    entry: {
        app: './app'
    },
    output: {
        path: path.join(__dirname, './public/'),
        publicPath: '/public/‘,
        filename: 'main.js'
    },
    module: {
        rules: [{
                test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
                loader: 'url-loader?limit=1024&name=images/[hash:8].[name].[ext]’   //打包多个图片时
                //name 字段指定了在打包根目录(output.path)下生成名为 images 的文件夹,并在原图片名前加上8位 hash 值
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        css: ExtractTextPlugin.extract({
                            use: 'css-loader',
                            fallback: 'vue-style-loader'
                        })


                    },

                }
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                // use: [
                //     'style-loader',
                //     'css-loader'
                // ]
                use: ExtractTextPlugin.extract({
                    use: 'css-loader',
                    fallback: 'style-loader'
                })
            }
        ]
    },
    plugins: [
        //重命名提取后的CSS文件
        new ExtractTextPlugin("main.css")
    ]

};

module.exports = config;
$ npm run build     //打包
此时打包后的 index_prod.html在public 文件夹下,打包后的代码如下所示

打包之后的Index_prod.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>dailypaper</title>
    <link rel="stylesheet" type="text-css" href="/public_CDN/static/css/app.ba3073bb7bb28cda7d30.css">
</head>
<body>
    <div id="app">

    </div>
    <script type='text/javascript' src="/public_CDN/static/js/app.ba3073bb7bb28cda7d30.js"></script>
</body>
</html>

打包之后的目录如下

webpack配置

相关标签: webpack