当前位置:   article > 正文

不借助脚手架使用webpack4从0开始搭建一个完整vue开发环境_vebpack vue 非脚手架

vebpack vue 非脚手架

目录

一、安装webpack和webpack-cli

二、指令方式运行

三、配置文件方式运行

四、less-loader解析less

 五、一般es6语法转换

 六、JS兼容性处理(包括ie)

七、使用url-loader解析样式中的图片

 八、打包html中图片资源

九、打包html文件

十、打包字体等资源

十一、自动编译打包运行

十二、多页面配置打包

十三:ESLint 校验 JS 代码

十四、提取css成单独文件

 十五、添加css兼容

十六、打包 Ts 和 Scss

十七、压缩js、css和html

十八、Resolve 模块解析

十九、Source-Map 配置(devtool映射)

二十、watch 监听和 clean 清理

二十一、HMR 热替换

二十二、请求代理设置

二十三、支持vue单文件组件

 二十四:环境分离设置

二十五、webpack中path、outputPath、publicPath联系与区别

二十六、总结

二十七、项目完整代码


一、安装webpack和webpack-cli

  1. npm i webpack@4.41.2 webpack-cli@3.3.10 -g //全局安装,作为指令使用
  2. npm i webpack@4.41.2 webpack-cli@3.3.10 -D //本地安装,作为本地依赖使用

注意:如果是局部安装,则需要在package.json中配置scripts,通过运行"npm run start"或"npm start"运行webpack:

  1. {
  2. "scripts": {
  3. "start": "webpack"
  4. }
  5. }

二、指令方式运行

开发配置指令:

webpack src/js/index.js -o dist/js/index.js --mode=development

生产配置指令:

webpack src/js/index.js -o dist/js/index.js --mode=production

可在package.json中配置scripts,通过运行"npm run build"运行webpack:

  1. "scripts": {
  2. "build": "webpack src/js/index.js -o dist/js/index.js --mode=production"
  3. }

三、配置文件方式运行

webpack.config.js:

  1. /**
  2. * 此文件是webpack配置文件,用于指定webpack去执行哪些任务
  3. */
  4. const path = require('path');
  5. module.exports = {
  6. entry: './src/js/index.js', // 由cmd执行目录决定
  7. output: {
  8. path: path.resolve(__dirname, 'dist/js'), // 由当前文件所在位置和要生成的dist位置关系决定
  9. filename: 'bundle.js'
  10. },
  11. mode: 'development',
  12. devtool: 'inline-source-map'
  13. };

配置好上述文件后在cmd中通过:

webpack

命令即可运行

假如webpack配置文件为“./config/webpack.base.config.js”,则package.json中打包命令配置为:

  1. "scripts": {
  2. "build": "webpack --config ./config/webpack.base.config.js"
  3. }

四、less-loader解析less

概述:webpack不能直接解析less文件,需要借助loader编译解析。

1、安装loader:

npm i style-loader@2.0.0 css-loader@4.3.0 less-loader@7.0.1 less@3.12.2 -D

less-loader基于less,所以要安装less。

注意各包的版本,否则会报错。

package.json:

  1. {
  2. "name": "webpack4",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "index.js",
  6. "scripts": {
  7. "test": "echo \"Error: no test specified\" && exit 1"
  8. },
  9. "keywords": [],
  10. "author": "",
  11. "license": "ISC",
  12. "devDependencies": {
  13. "css-loader": "^4.3.0",
  14. "less": "^3.12.2",
  15. "less-loader": "^7.0.1",
  16. "style-loader": "^2.0.0",
  17. "webpack": "^4.41.2",
  18. "webpack-cli": "^3.3.10"
  19. }
  20. }

2、配置loader:

  1. /**
  2. * 此文件是webpack配置文件,用于指定webpack去执行哪些任务
  3. */
  4. const path = require('path');
  5. module.exports = {
  6. entry: './src/js/index.js', // 由cmd执行目录决定
  7. output: {
  8. path: path.resolve(__dirname, 'dist/js'), // 由当前文件所在位置和要生成的dist位置关系决定
  9. filename: 'bundle.js'
  10. },
  11. mode: 'production',
  12. //1、所有的loader都要添加在module对象的rules中
  13. //2、rules是一个数组,数组中的每一个对象就是一个loader
  14. //3、loader特点:下载后无需引入,只需申明
  15. module: {
  16. rules: [{
  17. test: /\.less$/, //匹配所有less文件
  18. use: [
  19. 'style-loader', //3、用于在html文档中创建一个style标签,将样式“塞”进去
  20. 'css-loader', //2、将less编译后的css转换为CommonJs的一个模块
  21. 'less-loader' //1、将less编译成为css,但不生成单独的css文件,在内存中
  22. ]
  23. }]
  24. }
  25. };

3、运行指令:webpack

附:

src/css/demo.less:

  1. .demo1{
  2. width: 500px;
  3. height: 500px;
  4. background: #FF0000;
  5. }
  6. .demo2{
  7. width: 200px;
  8. height: 200px;
  9. background: #000000;
  10. }

src/js/index.js: 

  1. import func1 from './moudle1'
  2. import func2 from './moudle2'
  3. import '../css/demo.less'
  4. console.log(func1(1, 2));
  5. console.log(func2(2, 3));
  6. console.log("webpack!");

index.html:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <div class='demo1'></div>
  11. <div class='demo2'></div>
  12. <script src="./dist/js/bundle.js"></script>
  13. </body>
  14. </html>

 五、一般es6语法转换

高版本的火狐、chrome等标准浏览器直接支持es6中const和箭头函数等一般语法及promise等高级语法,但低版本的火狐、chrome等标准浏览器及ie不行,使用babel-loader可以将一般es6语法转换成es5语法。

安装loader:

npm i babel-loader@8.1.0 @babel/core@7.11.6 @babel/preset-env@7.11.5 -D

babel-loader:与 Webpack 协同工作的模块,加载处理 js 文件;

@babel/core:Babel 编译器的核心模块,是 babel-loader 依赖;

@babel/preset-env:Babel 预置器,用于分析 ES6 语法;

配置loader:

  1. module: {
  2. rules: [{
  3. test: /\.m?js$/,
  4. exclude: /(node_modules)/,
  5. use: {
  6. loader: 'babel-loader',
  7. options: {
  8. presets: ['@babel/preset-env']
  9. }
  10. }
  11. }]
  12. }

我们在 src 中的 js 文件,使用 ES6 的箭头函数来尝试一下;

  1. let fn = (x, y) => x + y;
  2. console.log(fn(10, 20));

PS:在没有使用 Babel 时,它打包会原封不动的使用 ES6 语法;

PS:在使用 Babel 之后,编译后的代码如下:

  1. var fn = function fn(x, y) {
  2. return x + y;
  3. };
  4. console.log(fn(10, 20));

如果你使用了未纳入标准(提案中)的代码,打包时,它会提醒你安装相关插件:

  1. //提案中,尚未纳入标准的语法
  2. class Person {
  3. #name;
  4. constructor() {
  5. this.#name = 'Mr.Lee';
  6. }
  7. }

 安装相关插件:

npm i @babel/plugin-proposal-class-properties -D
  1. options: {
  2. presets : [
  3. '@babel/preset-env'
  4. ],
  5. plugins : [
  6. '@babel/plugin-proposal-class-properties'
  7. ]
  8. }

 六、JS兼容性处理(包括ie)

高版本的火狐、chrome等标准浏览器直接支持es6中const和箭头函数等一般语法及promise等高级语法,但低版本的火狐、chrome等标准浏览器及ie不行,使用polyfill或core.js可以将所有es6语法转换成es5语法,使得其兼容性更强(包括兼容ie)。

1、使用polyfill

安装polyfill:

cnpm i @babel/polyfill@7.12.1 -D

使用:

入口文件中直接引入:

import '@babel/polyfill'
  1. /**
  2. * 当前文件是入口文件,可汇总js、css、字体、图片、音频、视频
  3. */
  4. import '@babel/polyfill' //包括es6高级语法的转换,不管编码人员使用了哪些新语法,全部新语法都转换
  5. import module1 from './module1'
  6. import module2 from './module2'
  7. import module3 from './module3'
  8. import '../css/demo.less'
  9. module2().then(data => {
  10. console.log("promise resolve:" + data);
  11. }).catch(error => {
  12. console.log("promise reject:" + error);
  13. })
  14. console.log(module2);
  15. console.log(module3);
  16. setTimeout(function(){
  17. console.log("定时器到点了");
  18. }, 1000)

优点:解决babel只能转换部分低级语法的问题,引入polyfill后可转换高级语法,比如Promise。

缺点:将所有高级语法进行转换,不管实际使用情况。

2、借助core.js按需引入(babel+core.js,使用core.js时可以不用polyfill):

安装core-js:

npm i core-js@3.13.0 -D

使用core-js:

配置文件中loader方式引入

  1. module: {
  2. rules: [{
  3. test: /\.js$/,
  4. exclude: /(node_modules)/,
  5. use: {
  6. loader: 'babel-loader',
  7. options: {
  8. "presets": [
  9. ["@babel/preset-env", {
  10. useBuiltIns: "usage", //使用corejs的方式,表示按需加载
  11. corejs: { version: 3 }, //指定core-js的版本
  12. targets: { //要兼容的目标浏览器
  13. "chrome": "58",
  14. "ie": "9"
  15. }
  16. }]
  17. ],
  18. "cacheDirectory": false // 开启babel缓存,只编译未编译代码,可减少编译时间
  19. }
  20. }
  21. }]
  22. }

七、使用url-loader解析样式中的图片

图片文件分为css引入图片和html插入图片。css加载图片都是背景图。小图片采用base64转换字符串,小图片、大图片都需要单独的loader插件来完成。

用到的处理图片的loader插件如下:

  • file-loader:解析JavaScipt和css插入的图片;
  • url-loader:将图片转换为性价比最高的base64编码字符串(基于file-loader,file-loader有的功能它都有);
  • html-loader:将.html进行打包,从而解析img插入问题;

安装loader:

npm i file-loader@6.2.0 url-loader@4.1.1 -D

说明:url-loader基于file-loader,且多了能针对不同图片大小进行不同处理的功能。

配置loader:

  1. module: {
  2. rules: [{
  3. test: /\.(png|jpg|gif)$/,
  4. use: [
  5. {
  6. loader: 'url-loader', //url-loader依赖file-loader,使用了url-loader后file-loader可以不用
  7. options: {
  8. limit: 8192, //url-loader能将小于8k图片编译成base64,大的采用file-loader处理
  9. publicPath: './dist/images', //决定实际代码中的图片地址
  10. outputPath: 'images', //决定文件本地输出地址
  11. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  12. }
  13. }
  14. ]
  15. }]
  16. }

一定要注意webpack.config.js中publicPath路径,包含图片的样式打包后会放置在页面的style标签中,图片打包后会放置在dist/images目录下,根据页面和生成的图片的路径关系,所以publicPath为 './dist/images':

webpack.config.js: 

  1. /**
  2. * 此文件是webpack配置文件,用于指定webpack去执行哪些任务
  3. */
  4. const path = require('path');
  5. module.exports = {
  6. entry: './src/js/index.js', // 由cmd执行目录决定
  7. output: {
  8. path: path.resolve(__dirname, 'dist'), // 由当前文件所在位置和要生成的dist位置关系决定
  9. filename: './js/bundle.js'
  10. },
  11. mode: 'development',
  12. //1、所有的loader都要添加在module对象的rules中
  13. //2、rules是一个数组,数组中的每一个对象就是一个loader
  14. //3、loader特点:下载后无需引入,只需申明
  15. module: {
  16. rules: [{
  17. test: /\.less$/, //匹配所有less文件
  18. use: [
  19. 'style-loader', //3、用于在html文档中创建一个style标签,将样式“塞”进去
  20. 'css-loader', //2、将less编译后的css转换为CommonJs的一个模块
  21. 'less-loader' //1、将less编译成为css,但不生成单独的css文件,在内存中
  22. ]
  23. }, {
  24. test: /\.m?js$/,
  25. exclude: /(node_modules)/,
  26. use: {
  27. loader: 'babel-loader',
  28. options: {
  29. presets: ['@babel/preset-env']
  30. }
  31. }
  32. }, {
  33. test: /\.js$/,
  34. exclude: /(node_modules)/,
  35. use: {
  36. loader: 'babel-loader',
  37. options: {
  38. "presets": [
  39. ["@babel/preset-env", {
  40. useBuiltIns: "usage", //按需引入需要使用polyfill
  41. corejs: { version: 3 }, //解决不能找到core-js的问题
  42. targets: { //解决兼容性处理哪些浏览器
  43. "chrome": "58",
  44. "ie": "9"
  45. }
  46. }]
  47. ],
  48. "cacheDirectory": false // 开启babel缓存
  49. }
  50. }
  51. }, {
  52. test: /\.(png|jpg|gif)$/,
  53. use: [
  54. {
  55. loader: 'url-loader',
  56. options: {
  57. limit: 8192,
  58. publicPath: './dist/images', //决定图片的url路径
  59. outputPath: 'images', //决定文件本地输出路径
  60. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  61. }
  62. }
  63. ]
  64. }]
  65. }
  66. };

各loader版本:

  1. {
  2. "name": "webpack4",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "index.js",
  6. "scripts": {
  7. "test": "echo \"Error: no test specified\" && exit 1"
  8. },
  9. "keywords": [],
  10. "author": "",
  11. "license": "ISC",
  12. "devDependencies": {
  13. "@babel/core": "^7.11.6",
  14. "@babel/preset-env": "^7.11.5",
  15. "babel-loader": "^8.1.0",
  16. "css-loader": "^4.3.0",
  17. "file-loader": "^6.2.0",
  18. "less": "^3.12.2",
  19. "less-loader": "^7.0.1",
  20. "style-loader": "^2.0.0",
  21. "url-loader": "^4.1.1",
  22. "webpack": "^4.41.2",
  23. "webpack-cli": "^3.3.10"
  24. }
  25. }

index.js

  1. import func1 from './moudle1'
  2. import func2 from './moudle2'
  3. import '../css/demo.less'
  4. console.log(func1(1, 2));
  5. console.log(func2(2, 3));
  6. console.log("webpack!");

 moudle1.js

  1. const fun1 = (a, b) => {
  2. console.log("a + b = ", a+b);
  3. }
  4. module.exports = fun1;

moudle2.js

  1. const fun2 = (a, b) => {
  2. console.log("a + b = ", a+b);
  3. }
  4. module.exports = fun2;

 demo.less

  1. .demo1{
  2. width: 500px;
  3. height: 500px;
  4. background: #FF0000 url("../images/download.png");
  5. }
  6. .demo2{
  7. width: 200px;
  8. height: 200px;
  9. background: #000000;
  10. }

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <div class='demo1'></div>
  11. <div class='demo2'></div>
  12. <script src="./dist/js/bundle.js"></script>
  13. </body>
  14. </html>

 八、打包html中图片资源

概述:html中的图片url-loader没法处理,它只能处理js中引入的图片/样式中的图片,不能处理html中的img标签,需要引入html-loader处理。

添加图片:在src/index.html添加两个img标签。

安装loader:

npm i html-loader@1.1.0 -D

配置loader:

  1. module: {
  2. rules: [{
  3. test: /\.(html)$/,
  4. use: {
  5. loader: 'html-loader' // html-loader找到图片后自动交给url-loader处理
  6. }
  7. }]
  8. }

完整代码:

webpack.config.js:

  1. /**
  2. * 此文件是webpack配置文件,用于指定webpack去执行哪些任务
  3. */
  4. const HtmlWebpackPlugin = require('html-webpack-plugin');
  5. const path = require('path');
  6. module.exports = {
  7. entry: './src/js/index.js', // 由cmd执行目录决定
  8. output: {
  9. path: path.resolve(__dirname, 'dist'), // 由当前文件所在位置和要生成的dist位置关系决定
  10. filename: './js/bundle.js'
  11. },
  12. mode: 'development',
  13. //1、所有的loader都要添加在module对象的rules中
  14. //2、rules是一个数组,数组中的每一个对象就是一个loader
  15. //3、loader特点:下载后无需引入,只需申明
  16. module: {
  17. rules: [{
  18. test: /\.less$/, //匹配所有less文件
  19. use: [
  20. 'style-loader', //3、用于在html文档中创建一个style标签,将样式“塞”进去
  21. 'css-loader', //2、将less编译后的css转换为CommonJs的一个模块
  22. 'less-loader' //1、将less编译成为css,但不生成单独的css文件,在内存中
  23. ]
  24. }, {
  25. test: /\.m?js$/,
  26. exclude: /(node_modules)/,
  27. use: {
  28. loader: 'babel-loader',
  29. options: {
  30. presets: ['@babel/preset-env']
  31. }
  32. }
  33. }, {
  34. test: /\.(png|jpg|gif)$/,
  35. use: [
  36. {
  37. loader: 'url-loader',
  38. options: {
  39. limit: 8192,
  40. publicPath: './images', //决定图片的url路径
  41. outputPath: 'images', //决定文件本地输出路径
  42. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  43. }
  44. }
  45. ]
  46. }, {
  47. test: /\.(html)$/,
  48. use: {
  49. loader: 'html-loader'
  50. }
  51. }]
  52. },
  53. plugins: [new HtmlWebpackPlugin({
  54. template: "./src/index.html", // 以当前文件为模板创建新的html(1、结构和原来一样;2、会自动引入打包的资源),默认 ,路径由cmd执行目录决定
  55. filename: "index.html", // 打包后的index.html文件默认位于dist目录下
  56. })]
  57. };

一定要注意url-loader中的publicPath。

index.html:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <div class="demo1"></div>
  11. <div class="demo2"></div>
  12. <div><img src="./images/react.png"/></div>
  13. </body>
  14. </html>

demo.less:

  1. .demo1{
  2. width: 200px;
  3. height: 200px;
  4. background-image: url("../images/react.png");
  5. background-size: cover;
  6. }
  7. .demo2{
  8. width: 200px;
  9. height: 200px;
  10. background-image: url("../images/vue.jpg");
  11. background-size: cover;
  12. }

package.json:

  1. {
  2. "name": "webpack4",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "index.js",
  6. "scripts": {
  7. "test": "echo \"Error: no test specified\" && exit 1"
  8. },
  9. "keywords": [],
  10. "author": "",
  11. "license": "ISC",
  12. "devDependencies": {
  13. "@babel/core": "^7.11.6",
  14. "@babel/preset-env": "^7.11.5",
  15. "babel-loader": "^8.1.0",
  16. "css-loader": "^4.3.0",
  17. "file-loader": "^6.2.0",
  18. "html-loader": "^1.1.0",
  19. "html-webpack-plugin": "^3.2.0",
  20. "less": "^3.12.2",
  21. "less-loader": "^7.0.1",
  22. "style-loader": "^2.0.0",
  23. "url-loader": "^4.1.1",
  24. "webpack": "^4.41.2",
  25. "webpack-cli": "^3.3.10"
  26. },
  27. "dependencies": {}
  28. }

九、打包html文件

概述:html文件webpack不能解析,需要借助插件编译解析。

添加html文件:

  1. src/index.html
  2. 注意:不要在html中引入任何css和js文件

安装插件Plugins

npm i html-webpack-plugin@3.2.0 -D

在webpack.config.js中引入插件(插件都需手动引入,而loader会自动加载):

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

配置插件:

  1. plugins: [new HtmlWebpackPlugin({
  2. template: './src/index.html', //以当前文件为模板创建新的html(1、结构和原来一样;2、会自动引入打包的资源),默认。路径相对于npm命令执行所在目录。
  3. filename: 'index.html' // 打包后的index.html文件默认位于dist目录下
  4. })]

运行指令:

webpack

完整代码:

src/index.html:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <div class='demo1'></div>
  11. <div class='demo2'></div>
  12. </body>
  13. </html>

src/js/index.js:

  1. import func1 from './moudle1'
  2. import func2 from './moudle2'
  3. import '../css/demo.less'
  4. const word = "webpack!";
  5. console.log("webpack!");
  6. console.log(func1(1, 2));
  7. func2().then(data=>{
  8. console.log(data);
  9. }).catch(error=>{
  10. console.log(error);
  11. })

删除

import '@babel/polyfill'

 webpack.config.js: 

  1. /**
  2. * 此文件是webpack配置文件,用于指定webpack去执行哪些任务
  3. */
  4. const HtmlWebpackPlugin = require('html-webpack-plugin');
  5. const path = require('path');
  6. module.exports = {
  7. entry: './src/js/index.js', // 由cmd执行目录决定
  8. output: {
  9. path: path.resolve(__dirname, 'dist'), // 由当前文件所在位置和要生成的dist位置关系决定
  10. filename: './js/bundle.js'
  11. },
  12. mode: 'development',
  13. //1、所有的loader都要添加在module对象的rules中
  14. //2、rules是一个数组,数组中的每一个对象就是一个loader
  15. //3、loader特点:下载后无需引入,只需申明
  16. module: {
  17. rules: [{
  18. test: /\.less$/, //匹配所有less文件
  19. use: [
  20. 'style-loader', //3、用于在html文档中创建一个style标签,将样式“塞”进去
  21. 'css-loader', //2、将less编译后的css转换为CommonJs的一个模块
  22. 'less-loader' //1、将less编译成为css,但不生成单独的css文件,在内存中
  23. ]
  24. }, {
  25. test: /\.m?js$/,
  26. exclude: /(node_modules)/,
  27. use: {
  28. loader: 'babel-loader',
  29. options: {
  30. presets: ['@babel/preset-env']
  31. }
  32. }
  33. }, {
  34. test: /\.js$/,
  35. exclude: /(node_modules)/,
  36. use: {
  37. loader: 'babel-loader',
  38. options: {
  39. "presets": [
  40. ["@babel/preset-env", {
  41. useBuiltIns: "usage", //按需引入需要使用polyfill
  42. corejs: { version: 3 }, //解决不能找到core-js的问题
  43. targets: { //解决兼容性处理哪些浏览器
  44. "chrome": "58",
  45. "ie": "9"
  46. }
  47. }]
  48. ],
  49. "cacheDirectory": false // 开启babel缓存
  50. }
  51. }
  52. }, {
  53. test: /\.(png|jpg|gif)$/,
  54. use: [
  55. {
  56. loader: 'url-loader',
  57. options: {
  58. limit: 8192,
  59. publicPath: './images', //决定图片的url路径
  60. outputPath: 'images', //决定文件本地输出路径
  61. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  62. }
  63. }
  64. ]
  65. }]
  66. },
  67. plugins: [new HtmlWebpackPlugin({
  68. template: "./src/index.html", // 以当前文件为模板创建新的html(1、结构和原来一样;2、会自动引入打包的资源),默认 ,路径由cmd执行目录决定
  69. filename: "index.html", // 打包后的index.html文件默认位于dist目录下
  70. })]
  71. };

十、打包字体等资源

概述:其它资源,比如图标,webpack不能解析,需要借助loader编译解析。

安装loader:

npm i file-loader@6.2.0 -D

配置loader:

  1. {
  2. test: /\.(eot|svg|woff|woff2|ttf|mp3|mp4|avi)$/,
  3. use: [
  4. {
  5. loader: 'file-loader',
  6. options: {
  7. outputPath: 'media', //决定文件本地输出路径
  8. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  9. }
  10. }
  11. ]
  12. }

src/index.html中添加字体标签:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <span class="icon iconfont icon-caiwuguanli"></span>
  11. <span class="icon iconfont icon-baojiaguanli"></span>
  12. <span class="icon iconfont icon-baoguanzhidantaitouguanli"></span>
  13. <span class="icon iconfont icon-caigoudingdan"></span>
  14. <span class="icon iconfont icon-cangchuguanli"></span>
  15. <span class="icon iconfont icon-caigoulujing"></span>
  16. <div class='demo1'></div>
  17. <div class='demo2'></div>
  18. <div><img src="./images/react.png" width="100" /></div>
  19. </body>
  20. </html>

添加字体样式文件src/css/iconfont.less:

  1. @font-face {
  2. font-family: "iconfont"; /* Project id */
  3. src: url('../media/iconfont.ttf?t=1621867822279') format('truetype');
  4. }
  5. .iconfont {
  6. font-family: "iconfont" !important;
  7. font-size: 16px;
  8. font-style: normal;
  9. -webkit-font-smoothing: antialiased;
  10. -moz-osx-font-smoothing: grayscale;
  11. }
  12. .icon-caiwuguanli:before {
  13. content: "\e609";
  14. }
  15. .icon-baojiaguanli:before {
  16. content: "\e60a";
  17. }
  18. .icon-baoguanzhidantaitouguanli:before {
  19. content: "\e60b";
  20. }
  21. .icon-caigoudingdan:before {
  22. content: "\e60c";
  23. }
  24. .icon-cangchuguanli:before {
  25. content: "\e60d";
  26. }
  27. .icon-caigoulujing:before {
  28. content: "\e60e";
  29. }

index.js中引入iconfont.less文件:

  1. import func1 from './moudle1'
  2. import func2 from './moudle2'
  3. import '../css/demo.less'
  4. import '../css/iconfont.less'
  5. const word = "webpack!";
  6. console.log("webpack!");
  7. console.log(func1(1, 2));
  8. func2().then(data=>{
  9. console.log(data);
  10. }).catch(error=>{
  11. console.log(error);
  12. })

运行指令:

webpack

文件夹结构:

iconfont.less(注意引用的字体路径):

  1. @font-face {
  2. font-family: "iconfont"; /* Project id */
  3. src: url('../media/iconfont.ttf?t=1621867822279') format('truetype');
  4. }
  5. .iconfont {
  6. font-family: "iconfont" !important;
  7. font-size: 16px;
  8. font-style: normal;
  9. -webkit-font-smoothing: antialiased;
  10. -moz-osx-font-smoothing: grayscale;
  11. }
  12. .icon-caiwuguanli:before {
  13. content: "\e609";
  14. }
  15. .icon-baojiaguanli:before {
  16. content: "\e60a";
  17. }
  18. .icon-baoguanzhidantaitouguanli:before {
  19. content: "\e60b";
  20. }
  21. .icon-caigoudingdan:before {
  22. content: "\e60c";
  23. }
  24. .icon-cangchuguanli:before {
  25. content: "\e60d";
  26. }
  27. .icon-caigoulujing:before {
  28. content: "\e60e";
  29. }

index.html:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <span class="icon iconfont icon-caiwuguanli"></span>
  11. <span class="icon iconfont icon-baojiaguanli"></span>
  12. <span class="icon iconfont icon-baoguanzhidantaitouguanli"></span>
  13. <span class="icon iconfont icon-caigoudingdan"></span>
  14. <span class="icon iconfont icon-cangchuguanli"></span>
  15. <span class="icon iconfont icon-caigoulujing"></span>
  16. <div class="demo1"></div>
  17. <div class="demo2"></div>
  18. <div><img src="./images/react.png"/></div>
  19. </body>
  20. </html>

webpack.config.js:

  1. /**
  2. * 此文件是webpack配置文件,用于指定webpack去执行哪些任务
  3. */
  4. const HtmlWebpackPlugin = require('html-webpack-plugin');
  5. const path = require('path');
  6. module.exports = {
  7. entry: './src/js/index.js', // 由cmd执行目录决定
  8. output: {
  9. path: path.resolve(__dirname, 'dist'), // 由当前文件所在位置和要生成的dist位置关系决定
  10. filename: './js/bundle.js'
  11. },
  12. mode: 'development',
  13. //1、所有的loader都要添加在module对象的rules中
  14. //2、rules是一个数组,数组中的每一个对象就是一个loader
  15. //3、loader特点:下载后无需引入,只需申明
  16. module: {
  17. rules: [{
  18. test: /\.less$/, //匹配所有less文件
  19. use: [
  20. 'style-loader', //3、用于在html文档中创建一个style标签,将样式“塞”进去
  21. 'css-loader', //2、将less编译后的css转换为CommonJs的一个模块
  22. 'less-loader' //1、将less编译成为css,但不生成单独的css文件,在内存中
  23. ]
  24. }, {
  25. test: /\.m?js$/,
  26. exclude: /(node_modules)/,
  27. use: {
  28. loader: 'babel-loader',
  29. options: {
  30. presets: ['@babel/preset-env']
  31. }
  32. }
  33. }, {
  34. test: /\.(png|jpg|gif)$/,
  35. use: [
  36. {
  37. loader: 'url-loader',
  38. options: {
  39. limit: 8192,
  40. //publicPath: '../dist/images', //决定图片的url路径
  41. outputPath: 'images', //决定文件本地输出路径
  42. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  43. }
  44. }
  45. ]
  46. }, {
  47. test: /\.(html)$/,
  48. use: {
  49. loader: 'html-loader'
  50. }
  51. }, {
  52. test: /\.(eot|svg|woff|woff2|ttf|mp3|mp4|avi)$/,
  53. use: [
  54. {
  55. loader: 'file-loader',
  56. options: {
  57. outputPath: 'media', //决定文件本地输出路径
  58. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  59. }
  60. }
  61. ]
  62. }]
  63. },
  64. plugins: [new HtmlWebpackPlugin({
  65. template: "./src/index.html", // 以当前文件为模板创建新的html(1、结构和原来一样;2、会自动引入打包的资源),默认 ,路径由cmd执行目录决定
  66. filename: "index.html", // 打包后的index.html文件默认位于dist目录下
  67. })]
  68. };

package.json:

  1. {
  2. "name": "webpack4",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "index.js",
  6. "scripts": {
  7. "test": "echo \"Error: no test specified\" && exit 1"
  8. },
  9. "keywords": [],
  10. "author": "",
  11. "license": "ISC",
  12. "devDependencies": {
  13. "@babel/core": "^7.11.6",
  14. "@babel/preset-env": "^7.11.5",
  15. "babel-loader": "^8.1.0",
  16. "css-loader": "^4.3.0",
  17. "file-loader": "^6.2.0",
  18. "html-loader": "^1.1.0",
  19. "html-webpack-plugin": "^3.2.0",
  20. "less": "^3.12.2",
  21. "less-loader": "^7.0.1",
  22. "style-loader": "^2.0.0",
  23. "url-loader": "^4.1.1",
  24. "webpack": "^4.41.2",
  25. "webpack-cli": "^3.3.10"
  26. },
  27. "dependencies": {}
  28. }

十一、自动编译打包运行

由于代码可能有CommonJS等非浏览器支持的语法,每次都必须打包才行运行,虽然借助Webstorm等工具可以构建服务器环境,但实际上不能时时监控刷新。IDE提供的服务器之间访问的是打包后的文件,是否监听时时刷新看个人习惯。

以上:如果要方便的话,开发者需求的想法是,开发时方便调试,最后再打包。所以,官方提供了Webpack-dev-Server工具来解决这个问题,支持特性:

  • 支持HTTP服务访问:localhost,127.0.0.1这种;
  • 监听变化时时刷新网页,时时预览;
  • 支持SourceMap;

注:

此处是自动刷新整个页面 ,如果想做到局部刷新,则请浏览二十二、HMR 热替换

1、安装loader:

npm i webpack-dev-server@3.11.2 -D

详情见:官网->指南->开发环境->使用webpack-dev-server

2、修改webpack配置对象:

  1. devServer: {
  2. open: true,
  3. compress: true,
  4. port: 3000,
  5. stats: 'minimal'//迷你型服务启动信息
  6. }

webpack.config.js: 

  1. /**
  2. * 此文件是webpack配置文件,用于指定webpack去执行哪些任务
  3. */
  4. const HtmlWebpackPlugin = require('html-webpack-plugin');
  5. const path = require('path');
  6. module.exports = {
  7. entry: './src/js/index.js', // 由cmd执行目录决定
  8. output: {
  9. path: path.resolve(__dirname, 'dist'), // 由当前文件所在位置和要生成的dist位置关系决定
  10. filename: './js/bundle.js' // 直接在根目录下生成js文件夹及bundle.js文件
  11. },
  12. mode: 'development',
  13. //1、所有的loader都要添加在module对象的rules中
  14. //2、rules是一个数组,数组中的每一个对象就是一个loader
  15. //3、loader特点:下载后无需引入,只需申明
  16. module: {
  17. rules: [{
  18. test: /\.less$/, //匹配所有less文件
  19. use: [
  20. 'style-loader', //3、用于在html文档中创建一个style标签,将样式“塞”进去
  21. 'css-loader', //2、将less编译后的css转换为CommonJs的一个模块
  22. 'less-loader' //1、将less编译成为css,但不生成单独的css文件,在内存中
  23. ]
  24. }, {
  25. test: /\.m?js$/,
  26. exclude: /(node_modules)/,
  27. use: {
  28. loader: 'babel-loader',
  29. options: {
  30. presets: ['@babel/preset-env']
  31. }
  32. }
  33. }, {
  34. test: /\.(png|jpg|gif)$/,
  35. use: [
  36. {
  37. loader: 'url-loader',
  38. options: {
  39. limit: 8192,
  40. //publicPath: '../dist/images', //决定图片的url路径
  41. outputPath: 'images', //决定文件本地输出路径
  42. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  43. }
  44. }
  45. ]
  46. }, {
  47. test: /\.(html)$/,
  48. use: {
  49. loader: 'html-loader'
  50. }
  51. }, {
  52. test: /\.(eot|svg|woff|woff2|ttf|mp3|mp4|avi)$/,
  53. use: [
  54. {
  55. loader: 'file-loader',
  56. options: {
  57. outputPath: 'media', //决定文件本地输出路径
  58. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  59. }
  60. }
  61. ]
  62. }]
  63. },
  64. plugins: [new HtmlWebpackPlugin({
  65. template: "./src/index.html", // 以当前文件为模板创建新的html(1、结构和原来一样;2、会自动引入打包的资源),默认 ,路径由cmd执行目录决定
  66. filename: "index.html", // 打包后的index.html文件默认位于dist目录下
  67. })],
  68. devServer: {
  69. open: true,
  70. compress: true,
  71. port: 8080,
  72. stats: 'minimal',//迷你型服务启动信息
  73. },
  74. };

3、修改url-loader部分配置:

  • 因为构建工具以build为根目录,不用再找build了
  • publicPath: '../build/images'-> 'images'

4、修改package.json中scripts指令:

"start": "webpack-dev-server --open chrome --port 3000"

 5、./index.html:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. 1
  11. <div class='demo1'></div>
  12. <div class='demo2'></div>
  13. <div><img src="./src/images/bg.jpeg"/></div>
  14. <script src="./js/bundle.js"></script>
  15. </body>
  16. </html>

6、运行指令:

npm start

经过以上设置,处理的html是根目录下的index.html,打包后的js位于设置的根目录下的js文件夹下。 

本地我们可以删除dist目录,还原打包之前再启动devServer测试效果。此时我们可以发现并不需要打包到本地,它是自动打包到内存让你时时预览调试的。也就是说:调试阶段,可以用devServer,完成了,再最终打包到本地即可。

十二、多页面配置打包

多页面配置

如果我们想生成多个.html 文件,比如 index.html 和 main.html,此时,我们需要修改一下入口文件和出口文件:

  1. //入口文件
  2. entry: {
  3. //把需要加载的 js 以键值对方
  4. index : './src/js/index.js',
  5. main : './src/js/main.js'
  6. },

  1. //入口文件,也支持 ES6 的箭头函数
  2. entry: () => ({
  3. index : './src/js/index.js',
  4. main : './src/js/main.js'
  5. }),

 出口文件,需要按照入口文件的名称进行打包,否则只会打包一个。

  1. //出口文件
  2. output: {
  3. //文件名
  4. filename : 'js/[name].js',
  5. }),

最后,我们要使用 HtmlWebpackPlugin 插件来设置自己想要的打包方案:

  1. //插件
  2. plugins: [
  3. new HtmlWebpackPlugin({
  4. template: "./src/index.html", //默认值
  5. filename: "index.html", //默认值
  6. chunks: ['index', 'main']
  7. }),
  8. new HtmlWebpackPlugin({
  9. template: "./src/main.html",
  10. filename: "main.html",
  11. chunks: ['main']
  12. }),
  13. ],

十三:ESLint 校验 JS 代码

基本的 ESLint 实现,需要一下安装以下模块:

  • eslint:JS 代码检查工具核心模块;
  • eslint-loader:webpack 协同模块;

首先,先安装 eslint,然后安装配置信息:

  1. npm i eslint@7.2.0 -D //安装 eslint
  2. .\node_modules\.bin\eslint --init //安装配置信息

PS:期间会让你选择配置信息情况,根据你实际情况选择即可,生成:.eslintrc.json;
PS:网上也会别人生成的配置信息可以拿来用,也可以去官网 eslint.cn/demo 生成信息

再次,我们安装 eslint-loader 模块:

npm i eslint-loader@4.0.2 -D

最后,我们来配置 webpack.config.js:

  1. {
  2. test : /.js$/,
  3. loader: 'eslint-loader',
  4. //编译前执行
  5. enforce: 'pre',
  6. //不检查的目录
  7. exclude: /node_modules/
  8. },

防止错误飘红太多,干扰演示,我们注释掉大部分代码,写上示例:

var foo = bar;

 测试打包和预览提示校验。

注意插件和loader的版本:

  1. {
  2. "name": "webpack4",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "index.js",
  6. "scripts": {
  7. "build": "webpack --config ./config/webpack.prod.config.js",
  8. "dev": "webpack-dev-server --open chrome --port 8080 --config ./config/webpack.dev.config.js",
  9. "start": "webpack-dev-server --open chrome --port 8080 --config ./config/webpack.dev.config.js"
  10. },
  11. "keywords": [],
  12. "author": "",
  13. "license": "ISC",
  14. "devDependencies": {
  15. "@babel/core": "^7.11.6",
  16. "@babel/polyfill": "^7.12.1",
  17. "@babel/preset-env": "^7.11.5",
  18. "autoprefixer": "^9.8.6",
  19. "axios": "^0.22.0",
  20. "babel-loader": "^8.1.0",
  21. "clean-webpack-plugin": "^4.0.0",
  22. "core-js": "^3.13.0",
  23. "css-loader": "^4.3.0",
  24. "eslint": "^7.2.0",
  25. "eslint-loader": "^4.0.2",
  26. "file-loader": "^6.2.0",
  27. "html-loader": "^1.1.0",
  28. "html-webpack-plugin": "^3.2.0",
  29. "less": "^3.12.2",
  30. "less-loader": "^7.0.1",
  31. "mini-css-extract-plugin": "^1.6.0",
  32. "optimize-css-assets-webpack-plugin": "^6.0.0",
  33. "postcss-flexbugs-fixes": "^4.2.1",
  34. "postcss-loader": "^3.0.0",
  35. "postcss-normalize": "^8.0.1",
  36. "postcss-preset-env": "^6.7.0",
  37. "style-loader": "^2.0.0",
  38. "url-loader": "^4.1.1",
  39. "vue-loader": "^15.9.8",
  40. "vue-template-compiler": "^2.6.14",
  41. "webpack": "^4.41.2",
  42. "webpack-cli": "^3.3.10",
  43. "webpack-dev-server": "^3.11.2",
  44. "webpack-merge": "^5.8.0"
  45. },
  46. "dependencies": {
  47. "vue": "^2.6.14"
  48. }
  49. }

十四、提取css成单独文件

  • 安装插件:
cnpm i mini-css-extract-plugin@1.6.0 -D
  • 引入插件:
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 
  • 配置插件:
  1. new MiniCssExtractPlugin({
  2. filename: 'css/[name].css'
  3. })
  • 配置loader:
  1. {
  2. test: /\.less$/, //匹配所有less文件
  3. use: [
  4. {
  5. loader: MiniCssExtractPlugin.loader,
  6. options: {
  7. publicPath: '../'
  8. }
  9. },
  10. 'css-loader', //2、将less编译后的css转换为CommonJs的一个模块
  11. 'less-loader' //1、将less编译成为css,但不生成单独的css文件,在内存中
  12. ]
  13. }
  • 运行指令:

package.json

  1. "scripts": {
  2. "build": "webpack",
  3. "build": "webpack --config ./config/webpack.prod.js",
  4. "dev": "webpack-dev-server --open chrome --port 8080 --config ./config/webpack.dev.js"
  5. },
npm run dev

完整代码:

src/index.html:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <span class="icon iconfont icon-caiwuguanli"></span>
  11. <span class="icon iconfont icon-baojiaguanli"></span>
  12. <span class="icon iconfont icon-baoguanzhidantaitouguanli"></span>
  13. <span class="icon iconfont icon-caigoudingdan"></span>
  14. <span class="icon iconfont icon-cangchuguanli"></span>
  15. <span class="icon iconfont icon-caigoulujing"></span>
  16. <div class='demo1'></div>
  17. <div class='demo2'></div>
  18. <div><img src="./images/react.png" width="100" /></div>
  19. </body>
  20. </html>

config/webpack.dev.js:

  1. const path = require('path')
  2. const HtmlWebpackPlugin = require("html-webpack-plugin")
  3. const MiniCssExtractPlugin = require('mini-css-extract-plugin')
  4. module.exports = {
  5. entry: './src/js/index.js', // 由cmd执行目录决定
  6. output: {
  7. path: path.resolve(__dirname, 'dist'), // 由当前文件所在位置和要生成的dist位置关系决定
  8. filename: './js/bundle.js'
  9. },
  10. module: {
  11. rules: [
  12. {
  13. test: /\.less$/,
  14. use: [
  15. {
  16. loader: MiniCssExtractPlugin.loader,
  17. options: {
  18. publicPath: '../'
  19. }
  20. },
  21. 'css-loader',
  22. 'less-loader'
  23. ]
  24. },
  25. {
  26. test: /\.m?js$/,
  27. exclude: /(node_modules)/,
  28. use: {
  29. loader: 'babel-loader',
  30. options: {
  31. "presets": [
  32. ["@babel/preset-env", {
  33. useBuiltIns: "usage", //按需引入需要使用polyfill
  34. corejs: { version: 3 }, //解决不能找到core-js的问题
  35. targets: { //解决兼容性处理哪些浏览器
  36. "chrome": "58",
  37. "ie": "9"
  38. }
  39. }]
  40. ],
  41. "cacheDirectory": false // 开启babel缓存,只编译未编译代码,可减少编译时间
  42. }
  43. }
  44. },
  45. {
  46. test: /\.(png|jpg|gif|jpeg)$/,
  47. use: {
  48. loader: 'url-loader',
  49. options: {
  50. limit: 8192,
  51. //publicPath: '../images',
  52. outputPath: 'images',
  53. name: '[hash:5].[ext]'
  54. }
  55. }
  56. },
  57. {
  58. test: /\.(html)$/,
  59. use: {
  60. loader: 'html-loader'
  61. }
  62. },
  63. {
  64. test: /\.(eot|svg|woff|woff2|ttf|mp3|mp4)$/,
  65. use: [{
  66. loader: 'file-loader',
  67. options: {
  68. //publicPath: '../media',
  69. outputPath: 'media',
  70. name: '[hash:5].[ext]'
  71. }
  72. }]
  73. }
  74. ]
  75. },
  76. plugins: [new HtmlWebpackPlugin({
  77. template: "./src/index.html", // 以当前文件为模板创建新的html(1、结构和原来一样;2、会自动引入打包的资源),默认 ,路径由cmd执行目录决定
  78. filename: "index.html", // 打包后的index.html文件默认位于dist目录下
  79. minify: {
  80. removeComments: true,
  81. collapseWhitespace: true,
  82. removeRedundantAttributes: true,
  83. useShortDoctype: true,
  84. removeEmptyAttributes: true,
  85. removeStyleLinkTypeAttributes: true,
  86. keepClosingSlash: true,
  87. minifyJS: true,
  88. minifyCSS: true,
  89. minifyURLs: true,
  90. }
  91. }), new MiniCssExtractPlugin({
  92. filename: './css/[name].css'
  93. })],
  94. devServer: {
  95. open: true,
  96. compress: true,
  97. port: 8080,
  98. hot: true
  99. }
  100. }

一定要注意:这里使用url-loader生成的背景图片是在css文件中引入,所有这里查找图片是从build/css目录去build/images目录查找:

  1. {
  2. test: /\.(png|jpg|gif)$/,
  3. use: [
  4. {
  5. loader: 'url-loader',
  6. options: {
  7. limit: 8192, //url-loader能将小于8k图片编译成base64,file-loader不具此功能
  8. //publicPath: '../images', //决定图片的url路径
  9. outputPath: 'images', //决定文件本地输出路径
  10. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  11. }
  12. }
  13. ]
  14. }

config/webpack.prod.js: 

  1. const path = require('path')
  2. const HtmlWebpackPlugin = require("html-webpack-plugin")
  3. const MiniCssExtractPlugin = require('mini-css-extract-plugin')
  4. module.exports = {
  5. entry: './src/js/index.js',
  6. output: {
  7. path: path.resolve(__dirname, '../dist'),
  8. filename: './js/bundle.js'
  9. },
  10. module: {
  11. rules: [
  12. {
  13. test: /\.less$/,
  14. use: [
  15. {
  16. loader: MiniCssExtractPlugin.loader,
  17. options: {
  18. publicPath: '../'
  19. }
  20. },
  21. 'css-loader',
  22. 'less-loader'
  23. ]
  24. },
  25. {
  26. test: /\.m?js$/,
  27. exclude: /(node_modules)/,
  28. use: {
  29. loader: 'babel-loader',
  30. options: {
  31. "presets": [
  32. ["@babel/preset-env", {
  33. useBuiltIns: "usage", //按需引入需要使用polyfill
  34. corejs: { version: 3 }, //解决不能找到core-js的问题
  35. targets: { //解决兼容性处理哪些浏览器
  36. "chrome": "58",
  37. "ie": "9"
  38. }
  39. }]
  40. ],
  41. "cacheDirectory": false // 开启babel缓存,只编译未编译代码,可减少编译时间
  42. }
  43. }
  44. },
  45. {
  46. test: /\.(png|jpg|gif|jpeg)$/,
  47. use: {
  48. loader: 'url-loader',
  49. options: {
  50. limit: 8192,
  51. //publicPath: '../images',
  52. outputPath: 'images',
  53. name: '[hash:5].[ext]'
  54. }
  55. }
  56. },
  57. {
  58. test: /\.(html)$/,
  59. use: {
  60. loader: 'html-loader'
  61. }
  62. },
  63. {
  64. test: /\.(eot|svg|woff|woff2|ttf|mp3|mp4)$/,
  65. use: [{
  66. loader: 'file-loader',
  67. options: {
  68. //publicPath: '../media',
  69. outputPath: 'media',
  70. name: '[hash:5].[ext]'
  71. }
  72. }]
  73. }
  74. ]
  75. },
  76. plugins: [new HtmlWebpackPlugin({
  77. template: './src/index.html',
  78. minify: {
  79. removeComments: true,
  80. collapseWhitespace: true,
  81. removeRedundantAttributes: true,
  82. useShortDoctype: true,
  83. removeEmptyAttributes: true,
  84. removeStyleLinkTypeAttributes: true,
  85. keepClosingSlash: true,
  86. minifyJS: true,
  87. minifyCSS: true,
  88. minifyURLs: true,
  89. }
  90. }), new MiniCssExtractPlugin({
  91. filename: './css/[name].css'
  92. })]
  93. }

 十五、添加css兼容

方法一:

  • 安装loader:
cnpm i postcss-loader@3.0.0 postcss-flexbugs-fixes@4.2.1 postcss-preset-env@6.7.0 postcss-normalize@8.0.1 autoprefixer@9.8.6 -D
  • 配置loader:
  1. {
  2. loader: require.resolve('postcss-loader'),
  3. options: {
  4. ident: 'postcss',
  5. plugins: () => [
  6. require('postcss-flexbugs-fixes'),
  7. require('postcss-preset-env')({
  8. autoprefixer: {
  9. flexbox: 'no-2009',
  10. },
  11. stage: 3,
  12. }),
  13. require('postcss-normalize')()
  14. ],
  15. sourceMap: true,
  16. },
  17. }
  • webpack.prod.js:
  1. /**
  2. * 此文件是webpack配置文件,用于指定webpack去执行哪些任务
  3. */
  4. const HtmlWebpackPlugin = require('html-webpack-plugin');
  5. const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  6. const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
  7. const path = require('path');
  8. module.exports = {
  9. entry: './src/js/index.js', // 由cmd执行目录决定
  10. output: {
  11. path: path.resolve(__dirname, '../build'), // 由当前文件所在位置和要生成的build位置关系决定
  12. filename: './js/bundle.js',
  13. publicPath: '/'
  14. },
  15. mode: 'production',
  16. devtool: 'cheap-module-source-map',
  17. module: {
  18. rules: [
  19. {
  20. test: /\.js$/,
  21. exclude: /(node_modules)/,
  22. use: {
  23. loader: 'babel-loader',
  24. options: {
  25. "presets": [
  26. ["@babel/preset-env", {
  27. useBuiltIns: "usage", //按需引入需要使用polyfill
  28. corejs: { version: 3 }, //解决不能找到core-js的问题
  29. targets: { //解决兼容性处理哪些浏览器
  30. "chrome": "58",
  31. "ie": "9"
  32. }
  33. }]
  34. ],
  35. "cacheDirectory": false // 开启babel缓存,只编译未编译代码,可减少编译时间
  36. }
  37. }
  38. },
  39. {
  40. test: /\.less$/, //匹配所有less文件
  41. use: [
  42. MiniCssExtractPlugin.loader, //3、用于在html文档中创建一个style标签,将样式“塞”进去
  43. 'css-loader', //2、将less编译后的css转换为CommonJs的一个模块
  44. {
  45. loader: require.resolve('postcss-loader'),
  46. options: {
  47. ident: 'postcss',
  48. plugins: () => [
  49. require('postcss-flexbugs-fixes'),
  50. require('postcss-preset-env')({
  51. autoprefixer: {
  52. flexbox: 'no-2009',
  53. },
  54. stage: 3,
  55. }),
  56. require('postcss-normalize')()
  57. ],
  58. sourceMap: true,
  59. },
  60. },
  61. 'less-loader' //1、将less编译成为css,但不生成单独的css文件,在内存中
  62. ]
  63. }, {
  64. test: /\.(png|jpg|gif)$/,
  65. use: [
  66. {
  67. loader: 'url-loader',
  68. options: {
  69. limit: 8192, //url-loader能将小于8k图片编译成base64,file-loader不具此功能
  70. //publicPath: '../images', //决定图片的url路径
  71. outputPath: 'images', //决定文件本地输出路径
  72. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  73. }
  74. }
  75. ]
  76. }, {
  77. test: /\.(eot|svg|woff|woff2|ttf|mp3|mp4|avi)$/,
  78. use: [
  79. {
  80. loader: 'file-loader',
  81. options: {
  82. outputPath: 'media', //决定文件本地输出路径
  83. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  84. }
  85. }
  86. ]
  87. }, {
  88. test: /\.(html)$/,
  89. use: {
  90. loader: 'html-loader'
  91. }
  92. }
  93. ]
  94. },
  95. plugins: [new HtmlWebpackPlugin({
  96. template: "./src/index.html", // 以当前文件为模板创建新的html(1、结构和原来一样;2、会自动引入打包的资源),默认 ,路径由cmd执行目录决定
  97. filename: "index.html", // 打包后的index.html文件默认位于dist目录下
  98. minify: {
  99. removeComments: true,
  100. collapseWhitespace: true,
  101. removeRedundantAttributes: true,
  102. useShortDoctype: true,
  103. removeStyleLinkTypeAttributes: true,
  104. keepClosingSlash: true,
  105. minifyJS: true,
  106. minifyCSS: true,
  107. minifyURLs: true,
  108. }
  109. }), new MiniCssExtractPlugin({
  110. filename: 'css/[name].css'
  111. }), new OptimizeCSSAssetsPlugin({
  112. cssProcessorPluginOptions: {
  113. preset: [
  114. 'default',
  115. {
  116. discardComments: {
  117. removeAll: true
  118. },
  119. },
  120. ]
  121. },
  122. cssProcessorOptions: {
  123. map: {
  124. inline: false,
  125. annotation: true
  126. }
  127. }
  128. })]
  129. };
  • 添加.browserslistrc文件:
  1. #Browsers that we support
  2. last 1 version
  3. > 1%
  4. IE 10 # sorry

方法二:

npm i postcss-loader@3.0.0 -D
  • 将'postcss-loader' 添加在loader最后:
  1. {
  2. test: /\.css$/,
  3. //执行顺序是从右往左边
  4. use : [
  5. {
  6. loader: MiniCssExtractPlugin.loader,
  7. options: {
  8. publicPath : '../'
  9. }
  10. },
  11. {
  12. loader: "css-loader",
  13. options: {
  14. importLoaders : 1 //由于采用了@import,被导入的css无法解析,需要设置importLoaders=1即可
  15. }
  16. },
  17. 'postcss-loader'
  18. ]
  19. }
  • 单有postcss-loader还不行,需要搭配创建autoprefixer插件转换。
npm i autoprefixer@9.8.6 -D

这个插件会在需要兼容性的样式中加上CSS前缀,比如:-ms、-webkit等。在根目录创建postcss.config.js用来配置兼容的浏览器,当postcss-loader被调用时postcss.config.js文件就会执行。

postcss.config.js

  1. /*
  2. postcss配置文件
  3. */
  4. const AutoPrefixer = require('autoprefixer');
  5. module.exports = {
  6. plugins : [
  7. new AutoPrefixer({
  8. overrideBrowserslist : [
  9. '> 0.15% in CN'
  10. //'ie >= 8'
  11. ]
  12. })
  13. ]
  14. };

在index.css中添加css样式:

  1. display: flex;
  2. transform: rotateY(130deg);

编译后看编译完成的css文件中是否有兼容性代码。

  • 除了兼容浏览器之外,还可以通过postcss-preset-env实现CSS4代码兼容。
npm i postcss-preset-env@6.7.0 -D

index.css中添加如下样式:

  1. :root{
  2. --green:green;
  3. };
  4. h1{
  5. color:var(--green);
  6. }

 postcss.config.js修改如下:

  1. //请注意:如果使用postcss-preset-env,就删除autoprefixer
  2. //因为post-preset-env集成了autoprefixer,不需要再引入设置
  3. // const AutoPrefixer = require('autoprefixer');
  4. const PostPresetEnv = require('postcss-preset-env');
  5. module.exports = {
  6. plugins : [
  7. new PostPresetEnv({
  8. browsers : [
  9. '> 0.15% in CN'
  10. //'ie >= 8'
  11. ]
  12. })
  13. ]
  14. };

编译后看编译完成的css文件中是否有兼容性代码。 

十六、打包 Ts 和 Scss

Scss

和 Less 一样,Scss 也是 Sass 的一种使用较多的语法;

cnpm install sass sass-loader node-sass -D

具体配置基本和 Less 一样,先创建.scss 文件,并引入:

  1. {
  2. test: /\.scss$/,
  3. //从右向左执行
  4. use : [
  5. MiniCssExtractPlugin.loader,
  6. 'css-loader',
  7. 'sass-loader'
  8. ]
  9. },

 TypeScript

越来越流行的 TypeScript,JavaScript 的一个超集。

cnpm i typescript ts-loader -D
  1. {
  2. test: /\.ts$/,
  3. use : 'ts-loader',
  4. }

 编写一个.ts 文件,然后通过 import 导入到 index.js。

  1. //type.ts
  2. export const output = (content : string) => {
  3. return content
  4. }
  5. //import ts
  6. import { output } from './type.ts'
  7. console.log(output('Mr.Lee'))

如果要省略掉 import 中文件后缀,需要配置:

  1. module.exports = {
  2. resolve: {
  3. extensions: ['.ts', '.js']
  4. }
  5. }

 PS:需要创建 tsconfig.json 文件。

十七、压缩js、css和html

为何要压缩代码?什么情况下要压缩?

答:在生产环境下打包时节约资源。

既然在生产环境,那首先要把打包的配置更改为生产环境:

mode: "production"

调节为生产环境打包,就会自动将 js 代码进行打包,不需要单独设置。

压缩css 

  • 安装插件:
npm i optimize-css-assets-webpack-plugin@6.0.0 -D
  • 引入插件:
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
  • 配置插件:
  1. new OptimizeCSSAssetsPlugin({
  2. cssProcessorPluginOptions: {
  3. preset: [
  4. 'default',
  5. {
  6. discardComments: {
  7. removeAll: true
  8. },
  9. },
  10. ]
  11. },
  12. cssProcessorOptions: {
  13. map: {
  14. inline: false,
  15. annotation: true
  16. }
  17. }
  18. })
  • 运行指令:
  1. npm run build
  2. serve -s build

webpack.prod.js:

  1. /**
  2. * 此文件是webpack配置文件,用于指定webpack去执行哪些任务
  3. */
  4. const HtmlWebpackPlugin = require('html-webpack-plugin');
  5. const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  6. const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
  7. const path = require('path');
  8. module.exports = {
  9. entry: './src/js/index.js', // 由cmd执行目录决定
  10. output: {
  11. path: path.resolve(__dirname, '../build'), // 由当前文件所在位置和要生成的build位置关系决定
  12. filename: './js/bundle.js',
  13. publicPath: '/'
  14. },
  15. mode: 'production',
  16. devtool: 'cheap-module-source-map',
  17. module: {
  18. rules: [
  19. {
  20. test: /\.js$/,
  21. exclude: /(node_modules)/,
  22. use: {
  23. loader: 'babel-loader',
  24. options: {
  25. "presets": [
  26. ["@babel/preset-env", {
  27. useBuiltIns: "usage", //按需引入需要使用polyfill
  28. corejs: { version: 3 }, //解决不能找到core-js的问题
  29. targets: { //解决兼容性处理哪些浏览器
  30. "chrome": "58",
  31. "ie": "9"
  32. }
  33. }]
  34. ],
  35. "cacheDirectory": false // 开启babel缓存,只编译未编译代码,可减少编译时间
  36. }
  37. }
  38. },
  39. {
  40. test: /\.less$/, //匹配所有less文件
  41. use: [
  42. MiniCssExtractPlugin.loader, //3、用于在html文档中创建一个style标签,将样式“塞”进去
  43. 'css-loader', //2、将less编译后的css转换为CommonJs的一个模块
  44. 'less-loader' //1、将less编译成为css,但不生成单独的css文件,在内存中
  45. ]
  46. }, {
  47. test: /\.(png|jpg|gif)$/,
  48. use: [
  49. {
  50. loader: 'url-loader',
  51. options: {
  52. limit: 8192, //url-loader能将小于8k图片编译成base64,file-loader不具此功能
  53. publicPath: '../images', //决定图片的url路径
  54. outputPath: 'images', //决定文件本地输出路径
  55. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  56. }
  57. }
  58. ]
  59. }, {
  60. test: /\.(eot|svg|woff|woff2|ttf|mp3|mp4|avi)$/,
  61. use: [
  62. {
  63. loader: 'file-loader',
  64. options: {
  65. outputPath: 'media', //决定文件本地输出路径
  66. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  67. }
  68. }
  69. ]
  70. }, {
  71. test: /\.(html)$/,
  72. use: {
  73. loader: 'html-loader'
  74. }
  75. }
  76. ]
  77. },
  78. plugins: [new HtmlWebpackPlugin({
  79. template: "./src/index.html", // 以当前文件为模板创建新的html(1、结构和原来一样;2、会自动引入打包的资源),默认 ,路径由cmd执行目录决定
  80. filename: "index.html", // 打包后的index.html文件默认位于dist目录下
  81. }), new MiniCssExtractPlugin({
  82. filename: 'css/[name].css'
  83. }), new OptimizeCSSAssetsPlugin({
  84. cssProcessorPluginOptions: {
  85. preset: [
  86. 'default',
  87. {
  88. discardComments: {
  89. removeAll: true
  90. },
  91. },
  92. ]
  93. },
  94. cssProcessorOptions: {
  95. map: {
  96. inline: false,
  97. annotation: true
  98. }
  99. }
  100. })]
  101. };

压缩html

修改前面安装的html-webpack-plugin插件配置:

  1. new HtmlWebpackPlugin({
  2. template: './src/index.html', //以当前文件为模板创建新的html(1、结构和原来一样;2、会自动引入打包的资源)
  3. minify: {
  4. removeComments: true, // 是否移除注释 默认 false
  5. collapseWhitespace: true, // 是否去除空格,默认 false
  6. removeRedundantAttributes: true,
  7. useShortDoctype: true,
  8. removeEmptyAttributes: true,
  9. removeStyleLinkTypeAttributes: true,
  10. keepClosingSlash: true,
  11. minifyJS: true,
  12. minifyCSS: true,
  13. minifyURLs: true,
  14. }
  15. })

十八、Resolve 模块解析

JS中,在 import 文件时如果不限定后缀会出现无法载入的情况,我们可以使用Resolve 模块中的extensions 来进行解析:

  1. //模块解析
  2. resolve: {
  3. //导入文件查找的限定后缀,默认.js 和.json
  4. extensions: ['.ts', '.js', '.json' ]
  5. },

PS:导入语句时如果检测不到指定的会报错。

alias 配置可以用别名的方式,将导入路径映射成一个新的路径:

  1. //设置一个别名路径(绝对路径)
  2. alias: {
  3. css : path.resolve(__dirname, './src/css')
  4. }
  5. require('css/base.css');

modules 配置可以指定 webpack 的解析模块目录:

  1. //找到解析模块目录,如果当前找不到就不断往上一层找
  2. modules: ['node_modules']
  3. //也可以设置指定目录直接查找,检查查找次数
  4. modules: [path.resolve(__dirname, '../node_modules')]

 PS:自然,也可以设置第二参数,防止第一参数找不到报错。

上述配置最终效果:

  1. resolve: {
  2. //导入语句省略后缀
  3. extensions: ['.ts', '.js', '.json'],
  4. //导入路径的别名
  5. alias: {
  6. css: path.resolve(__dirname, './src/css')
  7. },
  8. //解析模块目录
  9. // modules: [path.resolve(__dirname, '../node_modules'), 'node_modules']
  10. },

十九、Source-Map 配置(devtool映射)

Source-Map 可以将编译、打包、压缩后的代码映射到源代码上,你打包或运行的代码是编译后的,报错后devtool映射能指向你源代码的位置上,它会生成一个.map 文件。

配置方式:

devtool: 'source-map'

根据不同的方式,有下面几种类型:

  • source-map //打包后会生成一个对应的.map 文件
  • inline-source-map //打包后会在 js 文件的内部最后生成 map 内容
  • eval-source-map //打包后会在每个模块都执行 eval
  • hidden-source-map //打包后会生成.map 文件但不会追踪原始文件的错误代码
  • cheap-source-map //打包后会生成.map 并只能精确到行
  • PS:以上打包还可以合并比如 eval-cheap-source-map

在开发环境和生产环境,我们该如何选择?开发要求速度快,调试方便推荐:

  • eval-source-map 或 eval-cheap-source-map //开发环境
  • source-map //生产环境

二十、watch 监听和 clean 清理

1、watch 监听

每次打包,都比较烦,耗时耗力,有一种解决方案:watch 文件监听。这种解决方案,就是你打包时,就挂着监听你原始文件的变化,从而自动更新。

  1. //文件监听,默认 false
  2. watch: true,
  3. //开启 watch,下面才有意义
  4. watchOptions: {
  5. //不监听解析模块目录
  6. ignored: /node_modules/,
  7. //防止更新频率太快,默认 300 毫秒,意味监听到变化后 500 毫秒再编译
  8. aggregateTimeout: 500,
  9. //轮询间隔时间,1 秒,询问系统指定文件是否变化了
  10. poll: 1000
  11. },

2、clean 清理

每次打包之前都要手动清空设置的打包目录,因为不清空的话,改了配置目录就会多出废目录或文件。所以,使用 clean-webpack-plugin 插件,可以解决这个问题。

npm i clean-webpack-plugin -D
  1. //获取 clean 清理插件
  2. const { CleanWebpackPlugin } = require('clean-webpack-plugin')
  3. //插件
  4. plugins: [
  5. new CleanWebpackPlugin()
  6. ]

二十一、HMR 热替换

页面调试有一个问题,就是当我们编辑了 css 或 js它会自动刷新。但如果有大量的 css 或 js,一个小修改就要全部刷新影响开发性能。而 HMR 热替换就是解决这个问题,当 css 或 js 修改时只刷新修改的部分。对于html 文件,它就一个文件,不需要热替换。开启 HMR 热替换,可以在启动服务时加上--hot,或者在 devServer 配置:

  1. devServer: {
  2. hot : true
  3. }

对于 css 的热替换,需要使用 style-loader:

  1. {
  2. test: /\.less$/,
  3. use: [
  4. 'style-loader',
  5. 'css-loader',
  6. 'less-loader'
  7. ]
  8. }

当开启了 HMR 热替换之后,发现 html 文件修改后无法自动更新了,此时我们需要在入口文件加入这个 html 文件即可:

  1. entry: [
  2. './src/js/index.js',
  3. './src/index.html'
  4. ],

对于 js 的热替换,只要在入口文件对加载的其它 js 文件进行设置即可:

  1. import name from './module'
  2. console.log(name);
  3. if (module.hot) {
  4. module.hot.accept('./module', () => {
  5. console.log(name);
  6. })
  7. }

二十二、请求代理设置

这里提供两个远程 json 文件,会返回一些数据用于测试跨域问题:

https://cdn.liyanhui.com/data.json (可跨域,设置过)

https://cdn.ycku.com/data.json (不可跨域,默认)

安装 axios用于 ajax 测试:

npm install axios

编写代码,测试数据:

  1. import axios from 'axios'
  2. axios.get('https://cdn.liyanhui.com/data.json').then(res => {
  3. console.log(res.data)
  4. })

 如果把地址中的 liyanhui 换成 ycku 的话,会出现跨域的问题。

通过 devServer 设置代理模式,来解决跨域问题:

  1. devServer: {
  2. //设置代理
  3. proxy: {
  4. //匹配前缀为/api
  5. '/api': {
  6. //目标域名 ip
  7. target: 'https://cdn.ycku.com',
  8. //改变源
  9. changeOrigin: true,
  10. //重写 url, 去掉 /api
  11. pathRewrite: {
  12. '^/api': ''
  13. }
  14. }
  15. }
  16. }
axios.get('/api/data.json').then(res => { ... }).catch(error => {})

二十三、支持vue单文件组件

安装vue及相关插件

  1. cnpm i vue@2.6.14 -S
  2. cnpm i vue-loader@15.9.8 vue-template-compiler@2.6.14 -D

 webpack.config.js中解构VueLoaderPlugin:

const { VueLoaderPlugin } = require("vue-loader");

 webpack.config.js中加入vue-loader:

  1. {
  2. test: /\.vue$/, //匹配vue文件
  3. use: 'vue-loader'
  4. }

及VueLoaderPlugin插件:

plugins: [new VueLoaderPlugin()]

 完整的webpack.config.js:

  1. /**
  2. * 此文件是webpack配置文件,用于指定webpack去执行哪些任务
  3. */
  4. const HtmlWebpackPlugin = require('html-webpack-plugin');
  5. const { VueLoaderPlugin } = require("vue-loader");
  6. const path = require('path');
  7. module.exports = {
  8. entry: './src/js/index.js', // 由cmd执行目录决定
  9. output: {
  10. path: path.resolve(__dirname, 'dist'), // 由当前文件所在位置和要生成的dist位置关系决定
  11. filename: './js/bundle.js'
  12. },
  13. mode: 'development',
  14. //1、所有的loader都要添加在module对象的rules中
  15. //2、rules是一个数组,数组中的每一个对象就是一个loader
  16. //3、loader特点:下载后无需引入,只需申明
  17. module: {
  18. rules: [{
  19. test: /\.vue$/, //匹配所有less文件
  20. use: 'vue-loader'
  21. }, {
  22. test: /\.less$/, //匹配所有less文件
  23. use: [
  24. 'style-loader', //3、用于在html文档中创建一个style标签,将样式“塞”进去
  25. 'css-loader', //2、将less编译后的css转换为CommonJs的一个模块
  26. 'less-loader' //1、将less编译成为css,但不生成单独的css文件,在内存中
  27. ]
  28. }, {
  29. test: /\.m?js$/,
  30. exclude: /(node_modules)/,
  31. use: {
  32. loader: 'babel-loader',
  33. options: {
  34. presets: ['@babel/preset-env']
  35. }
  36. }
  37. }, {
  38. test: /\.js$/,
  39. exclude: /(node_modules)/,
  40. use: {
  41. loader: 'babel-loader',
  42. options: {
  43. "presets": [
  44. ["@babel/preset-env", {
  45. useBuiltIns: "usage", //按需引入需要使用polyfill
  46. corejs: { version: 3 }, //解决不能找到core-js的问题
  47. targets: { //解决兼容性处理哪些浏览器
  48. "chrome": "58",
  49. "ie": "9"
  50. }
  51. }]
  52. ],
  53. "cacheDirectory": false // 开启babel缓存
  54. }
  55. }
  56. }, {
  57. test: /\.(png|jpg|gif)$/,
  58. use: [
  59. {
  60. loader: 'url-loader',
  61. options: {
  62. limit: 8192,
  63. publicPath: './images', //决定图片的url路径
  64. outputPath: 'images', //决定文件本地输出路径
  65. name: '[hash:5].[ext]' //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  66. }
  67. }
  68. ]
  69. }]
  70. },
  71. plugins: [new VueLoaderPlugin()]
  72. };

新建vue相关文件:

src/ App.vue:

  1. <template>
  2. <div>
  3. {{message}}
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. data() {
  9. return {
  10. message: 'Hello Vue!'
  11. }
  12. }
  13. }
  14. </script>

src/index.js:

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. new Vue({
  4. render: h => h(App)
  5. }).$mount('#app')

dist/index.html:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <div id='app'></div>
  11. <script type="text/javascript" src="./js/bundle.js"></script></body>
  12. </html>

最后使用”npm run build“ 命令编译后打开”dist/index.html“页面即可查看最终效果。

 二十四:环境分离设置

当配置文件写的越发繁杂时,发现生产环境的配置和开发环境配置有冲突。此时,我们希望有两套配置文件,一套用于开发环境,一套用于生产环境。这里使用js合并插件webpack-merge来实现配置文件的分离保存。

1、创建文件夹config,将webpack.config.js复制两份:

./config/webpack.dev.config.js

./config/webpack.prod.config.js

2、将原先的webpack.config.js改为webpack.base.config.js,然后分离代码:

cnpm i webpack-merge -D
  1. //合并js插件
  2. const{ merge } = require('webpack-merge')
  3. //基础配置
  4. const base = require('./base.config')
  5. //开发环境配置
  6. module.exports = merge(base,{
  7. ...
  8. })

 webpack.base.config.js:

  1. // 路径
  2. const path = require("path");
  3. // html插件
  4. const HtmlWebpackPlugin = require("html-webpack-plugin");
  5. // 提取css为单独文件插件
  6. const MiniCssExtractPlugin = require("mini-css-extract-plugin");
  7. module.exports = {
  8. // 入口文件
  9. entry: "./src/js/index.js", // 由cmd执行目录决定
  10. // 出口文件
  11. output: {
  12. path: path.resolve(__dirname, "../dist"), // 由当前文件所在位置和要生成的dist位置关系决定
  13. filename: "./js/bundle.js"
  14. },
  15. // 模块解析
  16. resolve: {
  17. // 导入语句省略后缀
  18. extensions: [".ts", ".js", ".json", ".css", ".less", ".scss"],
  19. // 导入路径的别名
  20. alias: {
  21. css: path.resolve(__dirname, "./src/css")
  22. },
  23. // 解析模块目录
  24. modules: [path.resolve(__dirname, "../node_modules"), "node_modules"]
  25. },
  26. // 模块
  27. module: {
  28. rules: [
  29. {
  30. test: /\.less$/, // 匹配所有less文件
  31. use: [
  32. {
  33. loader: MiniCssExtractPlugin.loader,
  34. options: {
  35. publicPath: "../"
  36. }
  37. },
  38. "css-loader", // 2、将less编译后的css转换为CommonJs的一个模块
  39. "less-loader" // 1、将less编译成为css,但不生成单独的css文件,在内存中
  40. ]
  41. },
  42. {
  43. test: /\.js$/,
  44. exclude: /(node_modules)/,
  45. use: {
  46. loader: "babel-loader",
  47. options: {
  48. presets: [
  49. [
  50. "@babel/preset-env",
  51. {
  52. useBuiltIns: "usage", // 按需引入需要使用polyfill
  53. corejs: { version: 3 }, // 解决不能找到core-js的问题
  54. targets: {
  55. // 解决兼容性处理哪些浏览器
  56. chrome: "58",
  57. ie: "9"
  58. }
  59. }
  60. ]
  61. ],
  62. cacheDirectory: false // 开启babel缓存,只编译未编译代码,可减少编译时间
  63. }
  64. }
  65. },
  66. {
  67. test: /\.(png|jpg|gif)$/,
  68. use: [
  69. {
  70. loader: "url-loader", //url-loader依赖file-loader,使用了url-loader后file-loader可以不用
  71. options: {
  72. limit: 8192, //url-loader能将小于8k图片编译成base64,大的采用file-loader处理
  73. //publicPath: "./images", //决定图片的url路径,less处设置了,此处就不需要了,不然html中的图片路径会出错
  74. outputPath: "./images", //决定文件本地输出路径
  75. name: "[hash:5].[ext]" //修改文件名称,[hash:5]取hash值前5位,[ext]文件扩展名
  76. }
  77. }
  78. ]
  79. },
  80. {
  81. test: /\.(html)$/,
  82. use: {
  83. loader: "html-loader" // html-loader找到图片后自动交给url-loader处理
  84. }
  85. }
  86. ]
  87. },
  88. //插件
  89. plugins: [
  90. new HtmlWebpackPlugin({
  91. template: "./src/index.html", // 以当前文件为模板创建新的html(1、结构和原来一样;2、会自动引入打包的资源),默认 ,路径由cmd执行目录决定
  92. filename: "index.html", // 打包后的index.html文件默认位于dist目录下
  93. minify: {
  94. removeComments: true, // 是否移除注释 默认 false
  95. collapseWhitespace: true, // 是否去除空格,默认 false
  96. removeRedundantAttributes: true,
  97. useShortDoctype: true,
  98. removeEmptyAttributes: true,
  99. removeStyleLinkTypeAttributes: true,
  100. keepClosingSlash: true,
  101. minifyJS: true,
  102. minifyCSS: true,
  103. minifyURLs: true
  104. }
  105. }),
  106. new MiniCssExtractPlugin({
  107. filename: "css/[name].css"
  108. })
  109. ]
  110. };

webpack.dev.config.js

  1. // 合并js插件
  2. const { merge } = require("webpack-merge");
  3. // 公共基础配置
  4. const base = require("./webpack.base.config");
  5. // 开发环境配置
  6. module.exports = merge(base, {
  7. // devServer
  8. devServer: {
  9. open: true,
  10. compress: true,
  11. port: 8080,
  12. stats: "minimal", //迷你型服务启动信息
  13. // 代理
  14. proxy: {
  15. "/api": {
  16. target: "https://cdn.ycku.com",
  17. changeOrigin: true,
  18. pathRewrite: {
  19. "^/api": ""
  20. }
  21. }
  22. }
  23. },
  24. // devTool
  25. devtool: "eval-source-map",
  26. // 开发模式
  27. mode: "development"
  28. });

 webpack.prod.config.js:

  1. // 合并js插件
  2. const { merge } = require("webpack-merge");
  3. // 公共基础配置
  4. const base = require("./webpack.base.config");
  5. // css压缩插件
  6. const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
  7. // 清理打包目录插件
  8. const { CleanWebpackPlugin } = require("clean-webpack-plugin");
  9. module.exports = merge(base, {
  10. //devTool
  11. devtool: "source-map",
  12. //生产模式
  13. mode: "production",
  14. //监听
  15. watch: true,
  16. //监听选项,当true时才有效
  17. watchOptions: {
  18. //不监听解析模块目录
  19. ignored: /node_modules/,
  20. //更新频率
  21. aggregateTimeout: 500,
  22. //轮询
  23. poll: 1000
  24. },
  25. plugins: [
  26. new OptimizeCSSAssetsPlugin({
  27. cssProcessorPluginOptions: {
  28. preset: [
  29. "default",
  30. {
  31. discardComments: {
  32. removeAll: true
  33. }
  34. }
  35. ]
  36. },
  37. cssProcessorOptions: {
  38. map: {
  39. inline: false,
  40. annotation: true
  41. }
  42. }
  43. }),
  44. new CleanWebpackPlugin()
  45. ]
  46. });

 修改package.json的指令:

  1. "dev": "webpack-dev-server --open chrome --port 3000 --config ./config/webpack.dev.config.js",
  2. "start": "webpack-dev-server --open chrome --port 3000 --config ./config/webpack.dev.config.js",
  3. "build": "webpack --config ./config/webpack.prod.config.js"
  • 开发环境指令:
  1. npm start
  2. npm run dev
  • 生产环境指令:
npm run build

生产环境代码需要部署到服务器上才能运行,serve这个库能够快速帮我们搭建一个静态资源服务器:

npm i serve -g
serve -s build -p 5000

二十五、webpack中path、outputPath、publicPath联系与区别

path:仅告诉Webpack打包结果存储位置,必须是绝对路径。

outputPath:仅告诉各插件所生成文件的存放位置,该位置以path设置路径为基础,比如:output输出的js、url-loader解析的图片、HtmlWebpackPlugin生成的html文件都会存放在以path为基础的目录下。

publicPath:并不会对生成文件的路径造成影响,主要是在生产模式下,对你的页面里面引入的资源的路径做对应的补全,常见的就是css文件里面引入的图片、html文件里的url值补全。

请注意观察如下webpack.base.config.js文件中publicPath、outputPath及单独css文件夹设置:

项目路径 

webpack.base.config.js:

  1. const path = require('path')
  2. const HtmlWebpackPlugin = require("html-webpack-plugin")
  3. const MiniCssExtractPlugin = require('mini-css-extract-plugin')
  4. const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin') //压缩 css
  5. module.exports = {
  6. entry: './src/js/index.js', // 由cmd执行目录决定
  7. output: {
  8. path: path.resolve(__dirname, '../dist'), // 由当前文件所在位置和要生成的dist位置关系决定
  9. filename: 'js/bundle.js'
  10. },
  11. resolve: {
  12. //导入语句省略后缀
  13. extensions: ['.ts', '.js', '.json'],
  14. //导入路径的别名
  15. alias: {
  16. css: path.resolve(__dirname, './src/css')
  17. },
  18. //解析模块目录
  19. // modules: [path.resolve(__dirname, '../node_modules'), 'node_modules']
  20. },
  21. module: {
  22. rules: [
  23. {
  24. test: /\.less$/,
  25. use: [
  26. {
  27. loader: MiniCssExtractPlugin.loader,
  28. options: {
  29. publicPath: '../'
  30. }
  31. },
  32. 'css-loader',
  33. 'less-loader'
  34. ]
  35. },
  36. {
  37. test: /\.m?js$/,
  38. exclude: /(node_modules)/,
  39. use: {
  40. loader: 'babel-loader',
  41. options: {
  42. "presets": [
  43. ["@babel/preset-env", {
  44. useBuiltIns: "usage", //按需引入需要使用polyfill
  45. corejs: { version: 3 }, //解决不能找到core-js的问题
  46. targets: { //解决兼容性处理哪些浏览器
  47. "chrome": "58",
  48. "ie": "9"
  49. }
  50. }]
  51. ],
  52. "cacheDirectory": false // 开启babel缓存,只编译未编译代码,可减少编译时间
  53. }
  54. }
  55. },
  56. {
  57. test: /\.(png|jpg|gif|jpeg)$/,
  58. use: {
  59. loader: 'url-loader',
  60. options: {
  61. limit: 8192,
  62. outputPath: 'images',
  63. name: '[hash:5].[ext]'
  64. }
  65. }
  66. },
  67. {
  68. test: /\.(html)$/,
  69. use: {
  70. loader: 'html-loader'
  71. }
  72. },
  73. {
  74. test: /\.(eot|svg|woff|woff2|ttf|mp3|mp4)$/,
  75. use: [{
  76. loader: 'file-loader',
  77. options: {
  78. outputPath: 'media',
  79. name: '[hash:5].[ext]'
  80. }
  81. }]
  82. }
  83. ]
  84. },
  85. plugins: [new HtmlWebpackPlugin({
  86. template: "./src/index.html", // 以当前文件为模板创建新的html(1、结构和原来一样;2、会自动引入打包的资源),默认 ,路径由cmd执行目录决定
  87. filename: "index.html", // 打包后的index.html文件默认位于dist目录下
  88. minify: {
  89. removeComments: true, //去掉注释
  90. collapseWhitespace: true, //去掉空格
  91. removeRedundantAttributes: true,
  92. useShortDoctype: true,
  93. removeEmptyAttributes: true,
  94. removeStyleLinkTypeAttributes: true,
  95. keepClosingSlash: true,
  96. minifyJS: true,
  97. minifyCSS: true,
  98. minifyURLs: true,
  99. }
  100. }), new MiniCssExtractPlugin({
  101. filename: 'css/[name].css'
  102. }), new OptimizeCSSAssetsPlugin({
  103. cssProcessorPluginOptions: {
  104. preset: [
  105. 'default',
  106. {
  107. discardComments: {
  108. removeAll: true
  109. },
  110. },
  111. ]
  112. },
  113. cssProcessorOptions: {
  114. map: {
  115. inline: false,
  116. annotation: true
  117. }
  118. }
  119. })]
  120. }

二十六、总结

  1. entry: './src/js/index.js', // 由cmd执行目录决定
  2. output: {
  3. path: path.resolve(__dirname, '../dist'), // 由当前文件(webpack.config.js)所在位置和要生成的dist位置关系决定
  4. filename: 'js/bundle.js'
  5. }

1、明确生成的dist目录结构,比如./dist/images、./dist/css、./dist/js、./dist/index.html,根据此目录结构来确定配置文件中配置项publicPath的路径。

如果是开发模式,则是./images、./css、./js、./index.html结构。

二十七、项目完整代码

https://gitee.com/duansamve/webpack4-to-cli.githttps://gitee.com/duansamve/webpack4-to-cli.git

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/324080
推荐阅读
相关标签
  

闽ICP备14008679号