超详细使用webpack4.x搭建标准前端项目

Posted 卧梅又闻花

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了超详细使用webpack4.x搭建标准前端项目相关的知识,希望对你有一定的参考价值。

在开始教程前,先看看我们通过本教程能学到什么。

目录

1 小试牛刀

  1.1 创建并初始化项目

  1.2 创建目录及文件

  1.3 修改package.json

  1.4 编写项目代码

  1.5 配置webpack.config.js

  1.6 测试打包

2 搭建基础架构

  2.1 实现每次编译前自动清空dist目录

  2.2 实现从html模板自动生成最终html

  2.3 构建项目

3 搭建开发环境的热监测服务器

  3.1 安装webpack-dev-server

  3.2 使用source-map追踪源代码错误

4 分离生产环境和开发环境的配置文件

5 集成公用JS库(以jQuery为例)

  5.1 安装并集成jQuery

  5.2 全局应用jQuery

  5.3 使用jQuery

  5.4 单独打包jQuery

6 兼容IE8处理方式

  6.1 解决IE8“缺少标识符”错误

  6.2 解决ES6转ES5

  6.3 解决IE8“对象不支持bind属性方法”错误

7 CSS及Stylus的使用

  7.1 加载CSS和Stylus

  7.2 分离样式到css文件

  7.3 优化分离css公用样式

8 使用ejs将html模块化

9 加载图片资源

  9.1 css加载图片

  9.2 html加载图片

  9.3 解决css和html中引用图片路径不一致的问题

10 加载iconfont

11 使用cnpm加速下载

1 小试牛刀

1.1 创建并初始化项目

找个喜欢的目录,执行以下命令:

 
   
   
 
  1. mkdir webpack-demo

  2. cd webpack-demo

  3. npm init -y

  4. npm install webpack webpack-cli --save-dev

1.2 创建目录及文件

※注:本文代码区域每行开头的 “+”表示新增,“-或者D”表示删除,“M”表示修改,“...”表示省略。

dist为最终编译出来的生产环境代码,src为开发环境代码。

 
   
   
 
  1. /- webpack-demo

  2. |- package.json

  3. + |- /dist

  4. + |- index.html

  5. + |- /src

  6. + |- index.js

1.3 修改package.json

调整 package.json 文件,以便确保我们安装包是私有的(private),并且移除 main 入口。这可以防止意外发布你的代码。

同时加入script命令,让执行npx webpack 等同于执行npm run build。

 
   
   
 
  1. "name": "webpack-demo",

  2. "version": "1.0.0",

  3. "description": "",

  4. + "private": true,

  5. - "main": "index.js",

  6. "scripts": {

  7. - "test": "echo \"Error: no test specified\" && exit 1",

  8. + "build": "webpack --mode production",

  9. + "dev": "webpack --mode development"

  10. },

  11. ...

1.4 编写项目代码

编写dist/index.html,注意引入bundle.js(打包时会自动生成bundle.js)

 
   
   
 
  1. <!DOCTYPE html>

  2. <html lang="en">

  3. <head>

  4. <meta charset="UTF-8">

  5. <title>Webpack Demo</title>

  6. <script src="bundle.js"></script>

  7. </head>

  8. <body>

  9. </body>

  10. </html>

编写src/index.js,随便写点。

 
   
   
 
  1. document.write('hello world');

1.5 配置webpack.config.js

项目根目录创建webpack.config.js,用来配置webpack。

 
   
   
 
  1. |- package.json

  2. |- /dist

  3. |- index.html

  4. |- /src

  5. |- index.js

  6. + |- webpack.config.js

编写webpack.config.js:

 
   
   
 
  1. const path = require('path');

  2. module.exports = {

  3. // 入口js路径

  4. entry: './src/index.js',

  5. // 编译输出的js及路径

  6. output: {

  7. filename: 'bundle.js',

  8. path: path.resolve(__dirname, 'dist')

  9. }

  10. };

1.6 测试打包

执行npm run build,生成的dist如下:

 
   
   
 
  1. |- /dist

  2. |- index.html

  3. + |- bundle.js

浏览器运行index.html,显示“hello world”。

以上是最原始的方式,需要在dist配置html,这样并不科学。我们需要实现的是在src里开发,然后全部生成到dist中。请继续后面的章节。

2 搭建基础架构

2.1 实现每次编译前自动清空dist目录

安装clean-webpack-plugin,设置代码见2.3

 
   
   
 
  1. npm install clean-webpack-plugin --save-dev

2.2 实现从html模板自动生成最终html

安装html-webpack-plugin,设置代码见2.3

 
   
   
 
  1. npm install html-webpack-plugin --save-dev

2.3 构建项目

构建目录如下

 
   
   
 
  1. |- package.json

  2. |- webpack.config.js

  3. |- /dist

  4. |- /src

  5. |- /html

  6. |- index.html

  7. |- login.html

  8. |- /js

  9. |- index.js

  10. |- login.js

重新编写webpack.config.js

 
   
   
 
  1. const path = require('path');

  2. const {CleanWebpackPlugin} = require('clean-webpack-plugin');

  3. const HtmlWebpackPlugin = require('html-webpack-plugin');

  4. module.exports = {

  5. // 入口js路径

  6. entry: {

  7. index: './src/js/index.js',

  8. login: './src/js/login.js'

  9. },

  10. plugins: [

  11. // 自动清空dist目录

  12. new CleanWebpackPlugin(),

  13. // 设置html模板生成路径

  14. new HtmlWebpackPlugin({

  15. filename: 'index.html',

  16. template: './src/html/index.html',

  17. chunks: ['index']

  18. }),

  19. new HtmlWebpackPlugin({

  20. filename: 'login.html',

  21. template: './src/html/login.html',

  22. chunks: ['login']

  23. }),

  24. ],

  25. // 编译输出配置

  26. output: {

  27. // js生成到dist/js,[name]表示保留原js文件名

  28. filename: 'js/[name].js',

  29. // 输出路径为dist

  30. path: path.resolve(__dirname, 'dist')

  31. }

  32. };

现在执行npm run build,生成dist如下:

 
   
   
 
  1. |- /dist

  2. |- index.html

  3. |- login.html

  4. |- /js

  5. |- index.js

  6. |- login.js

查看html代码,发现对应的js已经被引入了。

3 搭建开发环境的热监测服务器

现在我们搭建一个基于nodejs的服务器,让代码运行在开发环境,并且实现在修改代码时不用刷新即可自动热更新页面。

3.1 安装webpack-dev-server

自动监测代码变化并实时刷新浏览器

 
   
   
 
  1. npm install webpack-dev-server --save-dev

修改package.json:

 
   
   
 
  1. "scripts": {

  2. "build": "webpack --mode production",

  3. - "dev": "webpack --mode development"

  4. + "serve": "webpack-dev-server --open --mode development"

  5. },

修改webpack.config.js:

 
   
   
 
  1. module.exports = {

  2. entry: {...},

  3. + // 动态监测并实时更新页面

  4. + devServer: {

  5. + contentBase: './dist',

  6. + // 默认8080,可不写

  7. + port: 8080,

  8. + // 热更新,无需刷新

  9. + hot: true

  10. + },

  11. plugins: [...],

  12. ...

  13. };

执行npm run serve,会在本地启动一个nodejs的web服务,浏览器会自动打http://localhost:8080/。

通过http://localhost:8080/login.html可以访问login页面。

这时修改src下的js或者html文件,页面会自动更新。

3.2 使用source-map追踪源代码错误

在编译生成的dist目录中,js代码已被重新混淆,如果出现错误,无法将错误正确定位到原始代码的对应位置,这样不方便调试生成环境的代码。如果需要精确调试生产环境代码,可通过source-map实现。(如果不需要此功能,可以跳过本节)

修改webpack.config.js:

inline-source-map: 将source map 转换为 DataUrl 后添加到页面的js中,生成的js文件较大(不推荐)

source-map: 生成对应的map文件,js较小,但是需要服务器设置不允许访问map文件(推荐)

 
   
   
 
  1. module.exports = {

  2. ...

  3. devServer: {...},

  4. + // 方便追踪源代码错误

  5. + devtool: 'source-map',

  6. plugins: [...],

  7. ..

  8. };

4 分离生产环境和开发环境的配置文件

webpack.config.js包含了生产环境和开发环境的配置,分离后,有利于代码的维护。

安装webpack-merge插件

使用装webpack-merge来实现拆分。

 
   
   
 
  1. npm install webpack-merge --save-dev

拆分webpack.config.js

新建以下3个文件: webpack.common.js (公共配置) webpack.dev.js (开发环境配置) webpack.prod.js (生产环境配置) 将webpack.config.js代码拆分后,可删除webpack.config.js。

 
   
   
 
  1. |- package.json

  2. - |- webpack.config.js

  3. + |- webpack.common.js

  4. + |- webpack.dev.js

  5. + |- webpack.prod.js

  6. |- /dist

  7. |- /src

webpack.common.js保留公共配置的代码

 
   
   
 
  1. const path = require('path');

  2. const HtmlWebpackPlugin = require('html-webpack-plugin');

  3. const {CleanWebpackPlugin} = require('clean-webpack-plugin');

  4. module.exports = {

  5. entry: {...},

  6. plugins: [...],

  7. output: {...}

  8. };

webpack.dev.js保留开发环境配置的代码

 
   
   
 
  1. const merge = require('webpack-merge');

  2. const common = require('./webpack.common');

  3. module.exports = merge(common, {

  4. // 动态监测并实时更新页面

  5. devServer: {

  6. contentBase: './dist',

  7. // 默认端口8080,可不填

  8. port: 8080,

  9. // 热更新,无需刷新

  10. hot: true

  11. }

  12. });

webpack.prod.js保留生产环境配置的代码

 
   
   
 
  1. const merge = require('webpack-merge');

  2. const common = require('./webpack.common');

  3. module.exports = merge(common, {

  4. // 方便追踪源代码错误

  5. //(如果不需要3.2小节的追踪功能,可以注释掉下行代码)

  6. devtool: 'source-map'

  7. });

修改package.json:

 
   
   
 
  1. "scripts": {

  2. M "build": "webpack --config webpack.prod.js --mode production",

  3. M "serve": "webpack-dev-server --open --config webpack.dev.js --mode development"

  4. },

5 集成公用JS库(以jQuery为例)

本节以jQuery为例,讲解如何引入公用JS库。如果使用AngularJS、React或者Vue,建议使用官方的CLI工具。

5.1 安装并集成jQuery

安装jQuery:

 
   
   
 
  1. npm install jquery --save

5.2 全局应用jQuery

jQuery是每个页面都要用的,在每个页面import太过于繁琐,修改webpack.common.js进行全局配置:

 
   
   
 
  1. ...

  2. + const webpack = require('webpack');


  3. module.exports = {

  4. ...

  5. plugins: [

  6. + new webpack.ProvidePlugin({

  7. + $: 'jquery',

  8. + jQuery: 'jquery'

  9. + }),

  10. new CleanWebpackPlugin(),

  11. ...

5.3 使用jQuery

修改src/html/index.html,加入div,用于测试:

 
   
   
 
  1. <!DOCTYPE html>

  2. <html lang="en">

  3. <head>

  4. <meta charset="UTF-8">

  5. <title>Webpack Demo</title>

  6. </head>

  7. <body>

  8. <div id="app">

  9. <div id="info"></div>

  10. </div>

  11. </body>

  12. </html>

修改src/js/index.js:

 
   
   
 
  1. $('#info').text('jQuery正常使用');

执行npm run build,生成dist如下:

 
   
   
 
  1. |- /dist

  2. |- index.html

  3. |- login.html

  4. |- /js

  5. |- index.js <--jQuery代码已集成到这里

  6. |- login.js

login.js没有jQuery代码是因为login.js里暂时还没用到jQuery,webpack的打包机制是“确实使用了”才会被真正打包进去。

如果我们的项目有很多html静态页,每个js都集成了jQuery,而且jQuery代码基本不会变动,这样就导致js文件冗余,我们可以把jQuery单独打包出来,可以方便浏览器缓存,减少请求的js大小。

5.4 单独打包jQuery

使用webpack的splitChunks来实现单独打包。

修改webpack.common.js:

 
   
   
 
  1. plugins: [

  2. ...

  3. // 设置html模板生成路径

  4. new HtmlWebpackPlugin({

  5. filename: 'index.html',

  6. template: './src/html/index.html',

  7. M chunks: ['jquery', 'index']

  8. }),

  9. new HtmlWebpackPlugin({

  10. filename: 'login.html',

  11. template: './src/html/login.html',

  12. M chunks: ['jquery', 'login']

  13. }),

  14. ],

  15. + optimization: {

  16. + splitChunks: {

  17. + cacheGroups: {

  18. + commons: {

  19. + test: /jquery/,

  20. + name: 'jquery',

  21. + chunks: 'all'

  22. + }

  23. + }

  24. + }

  25. + },

  26. // 编译输出配置

  27. output: {...}

执行npm run build,页面运行正常,生成dist如下:

 
   
   
 
  1. |- /dist

  2. |- index.html

  3. |- login.html

  4. |- /js

  5. |- index.js

  6. |- login.js

  7. + |- jquery.js <--jQuery已独立出来

6 兼容IE8处理方式

如果要兼容IE8等低版本浏览器,在开发过程中使用ES6等高版本js语法,会导低版本浏览器无法运行。另外,jQuery只能使用1.x,要安装低版本jQuery。(如果不需要兼容IE8,请直接跳过本章节)

首先,先安装兼容IE6~8的jQuery。

 
   
   
 
  1. npm install jquery-1x --save

修改webpack.common.js:

 
   
   
 
  1. ...

  2. plugins: [

  3. new webpack.ProvidePlugin({

  4. M $: 'jquery-1x',

  5. M jQuery: 'jquery-1x'

  6. }),

  7. ...

6.1 解决IE8“缺少标识符”错误

现在build出来的代码,IE8会在e.default代码处报错“缺少标识符”。需要安装uglifyjs-webpack-plugin。

 
   
   
 
  1. npm install uglifyjs-webpack-plugin --save-dev

修改webpack.common.js

 
   
   
 
  1. ...

  2. + const UglifyJsPlugin = require('uglifyjs-webpack-plugin');


  3. module.exports = {

  4. ...

  5. optimization: {

  6. splitChunks: { ... },

  7. + minimizer: [

  8. + new UglifyJsPlugin({

  9. + uglifyOptions: {

  10. + ie8: true

  11. + }

  12. + })

  13. + ]

  14. },

6.2 解决ES6转ES5

如果使用ES6语法,例如箭头函数,build会报错不通过。要把ES6转为ES5,需要安装以下插件(较多): babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime @babel/plugin-transform-modules-commonjs @babel/runtime

 
   
   
 
  1. npm install babel-loader @babel/core @babel/preset-env --save-dev

  2. npm install @babel/plugin-transform-runtime @babel/plugin-transform-modules-commonjs --save-dev

  3. npm install @babel/runtime --save

修改webpack.common.js,这里代码的作用是,在编译时把js文件中ES6转成ES5:

 
   
   
 
  1. optimization: {...},

  2. + module: {

  3. + rules: [

  4. + {

  5. + test: /\.js$/,

  6. + exclude: /(node_modules|bower_components)/,

  7. + use: {

  8. + loader: 'babel-loader',

  9. + options: {

  10. + presets: ['@babel/preset-env'],

  11. + plugins: [

  12. + '@babel/plugin-transform-runtime',

  13. + '@babel/plugin-transform-modules-commonjs'

  14. + ]

  15. + }

  16. + }

  17. + }

  18. + ]

  19. + },

  20. // 编译输出配置

  21. output: {...}

现在执行npm run build,编译通过。但是IE8下报错“对象不支持bind属性方法”,这是因为IE8不支持ES5,还需要引入es5-shim和es5-sham(见下节)。

6.3 解决IE8“对象不支持bind属性方法”错误

尝试了很多网上的方法,都没有尝试成功,最后干脆用直接引用的方法来解决。

下载插件

先去官网 https://github.com/es-shims/es5-shim/

下载es5-shim.min.js和es5-sham.min.js

在src下创建static目录,用于存放静态资源,通过使用CopyWebpackPlugin让static不被打包,直接copy到dist目录下。

 
   
   
 
  1. |- /src

  2. |- /css

  3. (略)

  4. |- /html

  5. |- index.html

  6. |- login.html

  7. |- /js

  8. (略)

  9. |- /static

  10. |- /js

  11. |- es5-shim.min.js

  12. |- es5-sham.min.js

然后,在src/html/index.html和src/html/login.html的里直接引入

 
   
   
 
  1. <head>

  2. <meta charset="UTF-8">

  3. <title>>Webpack Demo</title>

  4. + <script type="text/javascript" src="static/js/es5-shim.min.js"></script>

  5. </head>

es5-sham.min.js可在以后用到的时候再引入。

安装插件copy-webpack-plugin

 
   
   
 
  1. npm install --save-dev copy-webpack-plugin

修改webpack.common.js,代码作用是将src/static直接copy到dist,并重命名为static。

 
   
   
 
  1. ...

  2. + const CopyWebpackPlugin = require('copy-webpack-plugin');

  3. module.exports = {

  4. ...

  5. plugins: [

  6. ...

  7. new HtmlWebpackPlugin({

  8. filename: 'login.html',

  9. template: './src/html/login.html',

  10. chunks: ['jquery', 'login']

  11. }),

  12. + new CopyWebpackPlugin([

  13. + { from: './src/static', to: 'static' }

  14. + ])

执行npm run build,在IE8下可以愉快的运行啦。

7 CSS及Stylus的使用

7.1 加载CSS和Stylus

本节以Stylus为例,如果使用Sass/Less,可以参考本方法。混用CSS是为了同时掌握CSS使用方法。

安装相关依赖包:

 
   
   
 
  1. npm install style-loader css-loader --save-dev

  2. npm install stylus-loader stylus --save-dev

现在src目录如下:

 
   
   
 
  1. |- /src

  2. + |- /css

  3. + |- /common

  4. + |- common.css

  5. + |- frame.css (这个文件@import common.css和reset.css)

  6. + |- reset.css

  7. + |- /pages

  8. + |- index.styl

  9. + |- login.styl

  10. |- /html

  11. |- index.html

  12. |- login.html

  13. |- /js

  14. (略)

css及styl内的样式代码,请自行补充,这里不再展示了。

index.js中引入样式:

 
   
   
 
  1. import '../css/common/frame.css';

  2. import '../css/pages/index.styl';

login.js中引入样式:

 
   
   
 
  1. import '../css/common/frame.css';

  2. import '../css/pages/login.styl';

修改webpack.common.js:

 
   
   
 
  1. module.exports = {

  2. ...

  3. module: {

  4. rules: [

  5. + {

  6. + test: /\.css$/,

  7. + use: [

  8. + 'style-loader',

  9. + 'css-loader'

  10. + ]

  11. + },

  12. + {

  13. + test: /\.styl$/,

  14. + use: [

  15. + 'style-loader',

  16. + 'css-loader',

  17. + 'stylus-loader'

  18. + ]

  19. + }

  20. ...

执行build后,样式代码会直接打包插入到html文件中。

7.2 分离样式到css文件

现在我们想把样式通过link方式引入。

先安装MiniCssExtractPlugin

 
   
   
 
  1. npm install mini-css-extract-plugin --save-dev

然后修改webpack.common.js

 
   
   
 
  1. ···

  2. + const MiniCssExtractPlugin = require('mini-css-extract-plugin');


  3. module.exports = {

  4. plugins: [

  5. ...

  6. + new MiniCssExtractPlugin({

  7. + filename: 'css/[name].css'

  8. + }),

  9. new CopyWebpackPlugin([

  10. { from: './src/static', to: 'static' }

  11. ])

  12. ],

  13. module: {

  14. rules: [

  15. {

  16. test: /\.css$/,

  17. use: [

  18. + // 将原来的style-loader替换

  19. M MiniCssExtractPlugin.loader,

  20. 'css-loader'

  21. ]

  22. },

  23. {

  24. test: /\.styl$/,

  25. use: [

  26. + // 将原来的style-loader替换

  27. M MiniCssExtractPlugin.loader,

  28. 'css-loader',

  29. 'stylus-loader'

  30. ]

  31. }

  32. ···

执行npm run build,生成的dist如下:

 
   
   
 
  1. |- /dist

  2. |- index.html

  3. |- login.html

  4. + |- /css

  5. + |- index.css

  6. + |- login.css

  7. |- /js

  8. (略)

index.css和login.css都包含了公用样式,还可以进一步优化,把公用样式分离出来。

7.3 优化分离css公用样式

修改webpack.common.js,使用正则,把src/css/common/下的css单独打包并引用。

 
   
   
 
  1. ...

  2. plugins: [

  3. new HtmlWebpackPlugin({

  4. filename: 'index.html',

  5. template: './src/html/index.html',

  6. M chunks: ['style', 'jquery', 'index']

  7. }),

  8. new HtmlWebpackPlugin({

  9. filename: 'login.html',

  10. template: './src/html/login.html',

  11. M chunks: ['style', 'jquery', 'login']

  12. }),

  13. new MiniCssExtractPlugin({

  14. filename: 'css/[name].css'

  15. })

  16. ],

  17. optimization: {

  18. splitChunks: {

  19. cacheGroups: {

  20. commons: {

  21. test: /jquery/,

  22. name: 'jquery',

  23. chunks: 'all'

  24. },

  25. + styles: {

  26. + test: /[\\/]common[\\/].+\.css$/,

  27. + name: 'styles',

  28. + chunks: 'all',

  29. + enforce: true

  30. + }

  31. }

  32. }

  33. },

执行npm run build,生成的dist如下:

 
   
   
 
  1. |- /dist

  2. |- index.html

  3. |- login.html

  4. + |- /css

  5. + |- index.css

  6. + |- login.css

  7. |- style.css <-- 公用css

  8. |- /js

  9. |- index.js

  10. |- login.js

  11. |- jquery.js

  12. |- style.js <-- 怎么会有这个?

发现在dist/js/目录下会生成一个多余的styles.js,并且html也会引用这个多余的js。这是webpack4的bug,从2016年到现在处于open状态未解决,第三方插件都试过了,目前还没有解决,期待在webpack5中可以解决。

可以参看:https://github.com/webpack/webpack/issues/1967

网上解决方案中涉及到的第三方插件:

disable-output-webpack-plugin

html-webpack-exclude-assets-plugin

remove-source-webpack-plugin

以上插件N久没有更新了,在目前最新的webpack4.35.0中都无法使用。

8 使用ejs将html模块化

如果每个页面都有一个header,就可以把header抽成html模块,然后在需要的页面引入。这里通过ejs来实现。ejs本质还是个html,只不过多了些模板语法。

安装ejs-loader

 
   
   
 
  1. npm install ejs-loader --save-dev

以index.html为例,把index.html重命名为index.ejs

修改webpack.common.js,支持ejs:

 
   
   
 
  1. plugins: [

  2. ...

  3. new HtmlWebpackPlugin({

  4. filename: 'index.html',

  5. + // 这里将html改成ejs

  6. M template: './src/html/index.ejs',

  7. chunks: ['style', 'jquery', 'index']

  8. }),

  9. ...

  10. module: {

  11. rules: [

  12. ...

  13. + {

  14. + test: /\.ejs/,

  15. + use: ['ejs-loader'],

  16. + }

  17. ...

创建src/html/components/header/header.ejs

 
   
   
 
  1. <div id="header" class="G-header">这是公用头部</div>

在src/html/index.ejs引入即可。

 
   
   
 
  1. ...

  2. <div id="app">

  3. + <%= require('./components/header/header.ejs')() %>

  4. <div id="info"></div>

  5. </div>

  6. ...

9 加载图片资源

本章节介绍如何在css和html中引用图片。

安装插件file-loader和url-loader,url-loader基于file-loader,所以两个都要安装。 (也可以只使用file-loader,url-loader在file-loader的基础上扩展了功能,比如能设置小于多少KB的图片进行base64转码等)。

 
   
   
 
  1. npm install file-loader url-loader --save-dev

9.1 css加载图片

修改webpack.common.js

 
   
   
 
  1. module: {

  2. rules: [

  3. ...

  4. + {

  5. + test: /\.(png|svg|jpg|gif|webp)$/,

  6. + use: [

  7. + {

  8. + loader: 'url-loader',

  9. + options: {

  10. + // 最终生成的css代码中,图片url前缀

  11. + publicPath: '../images',

  12. + // 图片输出的实际路径(相对于dist)

  13. + outputPath: 'images',

  14. + // 当小于某KB时转为base64

  15. + limit: 0

  16. + }

  17. + }

  18. + ]

  19. + }

  20. ...

  21. ]

  22. },

在src/images里加入图片1.jpg

 
   
   
 
  1. |- /src

  2. |- /css

  3. (略)

  4. |- /html

  5. (略)

  6. + |- /images

  7. + |- 1.jpg

  8. |- /js

  9. (略)

  10. |- /static

  11. (略)

在src/css/pages/index.styl加入代码:

 
   
   
 
  1. .bg-pic

  2. width: 200px

  3. height: 200px

  4. background: url(../../images/1.jpg) no-repeat

在src/html/index.ejs加入代码:

 
   
   
 
  1. <div id="app">

  2. <%= require('./components/header/header.ejs')() %>

  3. <div id="info"></div>

  4. + <div class="bg-pic"></div>

  5. </div>

执行npm run build,图片可正常访问,生成dist目录如下:

 
   
   
 
  1. |- /dist

  2. |- /css

  3. (略)

  4. |- /images

  5. + |- f0a89ff457b237711f8306a000204128.jpg

  6. |- /js

  7. (略)

  8. |- /static

  9. (略)

  10. |- index.html

  11. |- login.html

9.2 html加载图片

 
   
   
 
  1. npm install html-loader --save-dev

在src/images里加入图片2.jpg

 
   
   
 
  1. |- /src

  2. |- /css

  3. (略)

  4. |- /html

  5. (略)

  6. |- /images

  7. |- 1.jpg

  8. + |- 2.jpg

  9. |- /js

  10. (略)

  11. |- /static

  12. (略)

修改webpack.common.js,这样可以把html中的图片提取并打包。

 
   
   
 
  1. module: {

  2. rules: [

  3. ...

  4. + {

  5. + test: /\.(html)$/,

  6. + use: {

  7. + loader: 'html-loader',

  8. + options: {

  9. + attrs: ['img:src', 'img:data-src', 'audio:src'],

  10. + minimize: true

  11. + }

  12. + }

  13. + }

  14. ...

在src/html/index.ejs加入代码:

 
   
   
 
  1. <div id="app">

  2. <%= require('./components/header/header.ejs')() %>

  3. <div id="info"></div>

  4. <div class="bg-pic"></div>

  5. + <img src="${require('../images/2.jpg')}" alt="">

  6. </div>

执行npm run build,图片已可正常访问,生成dist目录如下

 
   
   
 
  1. |- /dist

  2. |- /css

  3. (略)

  4. |- /images

  5. |- f0a89ff457b237711f8306a000204128.jpg

  6. + |- dab63db25d48455007edc5d81c476076.jpg

  7. |- /js

  8. (略)

  9. |- /static

  10. (略)

  11. |- index.html

  12. |- login.html

但是发现html中img的图片不能显示。查看生成的代码发现:

dist/index.html中的src为../images/xxxx.jpg

dist/css/index.css中background的url也为../images/xxxx.jpg

因为html和css的路径差了一级,导致路径不一致。因此需要区分html和css中的图片路径。

9.3 解决css和html中引用图片路径不一致的问题

修改webpack.common.js,将MiniCssExtractPlugin.loader改为对象的方式:

 
   
   
 
  1. module: {

  2. rules: [

  3. ...

  4. {

  5. test: /\.css$/,

  6. use: [

  7. M {

  8. M loader: MiniCssExtractPlugin.loader,

  9. M options: {

  10. M // css中的图片路径增加前缀

  11. M publicPath: '../'

  12. M }

  13. M },

  14. 'css-loader'

  15. ]

  16. },

  17. {

  18. test: /\.styl$/,

  19. use: [

  20. M {

  21. M loader: MiniCssExtractPlugin.loader,

  22. M options: {

  23. M // css中的图片路径增加前缀

  24. M publicPath: '../'

  25. M }

  26. M },

  27. 'css-loader',

  28. 'stylus-loader'

  29. ]

  30. },

  31. ...

  32. {

  33. test: /\.(png|svg|jpg|gif|webp)$/,

  34. use: [

  35. {

  36. loader: 'url-loader',

  37. options: {

  38. D // 最终生成的图片路径代码 (删除)

  39. D // publicPath: '../images', (删除)

  40. // 图片输出的实际路径

  41. outputPath: 'images',

  42. // 当小于某KB时转为base64

  43. limit: 0

  44. }

  45. }

  46. ]

  47. },

  48. ...

再执行npm run build,路径显示正常了。

10 加载iconfont

从阿里巴巴图标网站 https://www.iconfont.cn/ 下载字体和样式文件,导入到项目中,结构如下:

 
   
   
 
  1. |- /src

  2. |- /css

  3. |- /common

  4. |- common.css

  5. |- frame.css

  6. + |- iconfont.css

  7. |- reset.css

  8. |- /pages

  9. |- index.styl

  10. |- login.styl

  11. + |- /fonts

  12. + |- iconfont.eot

  13. + |- iconfont.svg

  14. + |- iconfont.ttf

  15. + |- iconfont.woff

  16. + |- iconfont.woff2

  17. |- /html

  18. (略)

  19. |- /images

  20. (略)

  21. |- /js

  22. (略)

  23. |- /static

  24. (略)

src/css/common/frame.css里要@import "iconfont.css",然后修改iconfont.css中每个字体的路径。

在src/html/index.ejs里直接使用字体(字体样式在iconfont网站定义):

 
   
   
 
  1. <i class="G-iconfont G-ficon-cart"></i>

修改webpack.common.js,

 
   
   
 
  1. module: {

  2. rules: [

  3. ...

  4. + {

  5. + test: /\.(woff|woff2|eot|ttf|svg)$/,

  6. + use: {

  7. + loader: 'file-loader',

  8. + options: {

  9. + // 保留原文件名和后缀名

  10. + name: '[name].[ext]',

  11. + // 输出到dist/fonts/目录

  12. + outputPath: 'fonts',

  13. + }

  14. + }

  15. + }

  16. ]

  17. },

执行npm run build, 生成dist目录如下:

 
   
   
 
  1. |- /dist

  2. |- /css

  3. (略)

  4. |- /images

  5. (略)

  6. + |- /fonts

  7. |- iconfont.eot

  8. |- iconfont.svg

  9. |- iconfont.ttf

  10. |- iconfont.woff

  11. |- /js

  12. (略)

  13. |- /static

  14. (略)

  15. |- index.html

  16. |- login.html

没有生成woff2文件,是因为css中没有引用。

11 使用cnpm加速下载

npm有时下载速度很慢,可以安装cnpm,从国内淘宝镜像下载,执行以下命令:

 
   
   
 
  1. npm install -g cnpm --registry=https://registry.npm.taobao.org

以后npm直接替换成cnpm使用。

以上就是基于webpack4.x搭建标准前端工程的技术分享。

本文在超详细使用webpack4.x搭建标准前端项目同步发布,点击“阅读原文”可跳转至“掘金”阅读。

以上是关于超详细使用webpack4.x搭建标准前端项目的主要内容,如果未能解决你的问题,请参考以下文章

脱离脚手架来配置学习 webpack4.x 基础搭建项目

使用SpringBoot一小时快速搭建一个简单后台管理(增删改查)(超详细教程)

一篇超详细的vue项目前端自动化测试教学!

一篇超详细的vue项目前端自动化测试教学!

一篇超详细的vue项目前端自动化测试教学!

超详细Web前端开发规范文档