webpack 学习笔记1(入门)

由于笔者的nodejs版本比较新,所以用webpack4会有一些bug。因此直接选择了webpack5

版本: node -v #v18.15.0

           webpack@5.78.0
            "webpack-cli@5.0.1

#1 安装

    采用本地安装,没有全局安装。因为不同的项目可能使用的webpack版本不同,所以全局安装会有一些问题。还是一个项目一个版本比较好。

    #由于本地无通过webpack -v ;webpack-cli -v 查看版本,不过可以直接在package.json里看到版本

    npm install -D webpack      #@5.78.0

    npm install -D webpack-cli    #@5.0.1

    

#2 一个极其简单的例子

     先写一个webpack.config.js文件,将login模块打包到build中

const path = require('path');
module.exports = {
    entry:    {
		"login":"./data/login.js"},
	output: {
		filename: '[name].js',		
		path: path.resolve(__dirname, 'build2'),
    	clean: true//自动删除之前的文件
	}
};

  

 

     然后写login代码(以及调用到的js的代码)

//login.js
const name = require("./name")
console.log("abc_log:",name);

  

//name.js
module.exports="jack";

  

     使用npm init初始化package.json文件,过程中选择webpack.config.js文件作为配置文件。

     注意在script中需要添加"build":"webpack xxxxxxx",因为webpack非全局安装,所以cmd中webpack命令无法直接使用。通过此方法然后调用  npm run build  就可以运行webpack了。

      如果不使用scripts的形式。直接打包使用命令  npx webpack --mode=development

{
  "name": "html",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.config.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build":"webpack --mode=development",
    "pro":"webpack --mode=production"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^5.78.0",
    "webpack-cli": "^5.0.1"
  }
}

  此时就生成了login.js的文件,如下(经过编码的,不过还是可以看到一些关键字):

(()=>{var o={341:o=>{o.exports="jack"}},r={};function t(e){var s=r[e];if(void 0!==s)return s.exports;var n=r[e]={exports:{}};return o[e](n,n.exports,t),n.exports}(()=>{const o=t(341);console.log("abc_log:",o)})()})();

  至此一个最最简单的实例就完成了。大的框架由此开始编写!

     

 #3. 用html-webpack-plugin,从模板html生成目标html

    npm install -D html-webpack-plugin    #笔者的版本是@5.5.0

    然后新建一个tpl.html模板如下:

<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no,maximum-scale=1" />
	<!--常用库写这里,.........-->
   <!-- 这里的titile在config.js中设置-->
    <title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
	<div id="content"></div>
</body>
</html>

  webpack.config.js新增配置如下:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装

const dist = "../../nginx-1.22.1/nginx-1.22.1/html/data";
module.exports = {
    entry:{
		"investors_shares":"./data/investors_shares.js"
    },
   output: {
      filename: '[name].[chunkhash].js',//模块名字+MD5
      path: path.resolve(__dirname, dist),
      clean: true//自动删除之前的文件
   },
   plugins:[
		new HtmlWebpackPlugin({
			title: "XXX",
			filename: "investors_shares.html",//目标文件
			template: "./data/tpl.html",//源文件
			inject: "body",//插入到body元素后
			minify:{
				removeComments:true//移除HTML中的注释
			},
                        chunks:["investors_shares","XXX"]//这里制定引入哪些js,如果不写,则默认引入html同名的
		}),
   ]
};    

  

 

 

运行npm run build后,生成一个js和一个html文件。可以直接用浏览器查看输出  

       

      

 

 #4 安装react react-dom 以及babel相关

      npm i -D react@15.4.2 react-dom@15.4.2   babel-loader  @babel/core @babel/preset-env   @babel/preset-react

笔者的最终安装版本如下:

  "devDependencies": {
    "@babel/core": "^7.21.4",
    "@babel/preset-env": "^7.21.4",
    "@babel/preset-react": "^7.18.6",
    "babel-loader": "^9.1.2",
    "react": "^15.4.2",
    "react-dom": "^15.4.2",
 。。。

  这里略作解释(参考http://events.jianshu.io/p/822b8cc0fb4e):

babel-loader:使用Babel转换JavaScript依赖关系的Webpack加载器, 简单来讲就是webpack和babel中间层,允许webpack在遇到js文件时用bable来解析

@babel/core:即babel-core,将ES6代码转换为ES5。7.0之后,包名升级为@babel/core。@babel相当于一种官方标记,和以前大家随便起名形成区别。

@babel/preset-env:即babel-preset-env,根据您要支持的浏览器,决定使用哪些transformations / plugins 和 polyfills,例如为旧浏览器提供现代浏览器的新特性。

@babel/preset-react:即 babel-preset-react,针对所有React插件的Babel预设,例如将JSX转换为函数.

 

编写webpack.config.js如下,新增了rules部分,如下:

XXX
	output: {
		XXX
	},
	module: {
		rules: [
			{
				test: /\.js|jsx$/,
				exclude: /(node_modules|bower_components)/,
				use: {
					loader: 'babel-loader',
					options: {
					  presets: [
						['@babel/preset-env', { targets: "defaults" }],
						['@babel/preset-react']
					  ]
					}
				  }
			}
		]
	},
	plugins:[
	XXX

  js部分如下随便添加一些代码:

let React = require('react');
let ReactDOM = require('react-dom');
let gf = require("./gf")
class Index extends React.Component{
    constructor(props) {
        super(props);
        this.state = {};
    }
    componentWillMount() {    }
    componentDidMount() {   }
    render () {
        return(
            <div>{gf.DOMAIN+"javamy"}</div>
        );
    }
}
ReactDOM.render(
    <Index />,
    document.getElementById('content')
);

 

gf.js如下

module.exports = {
  fun:(name)=>{
    return jack;
  },
 DOMAIN : '//' + location.host + '/api'
}

  

  运行npm run build,就生成了一个很大的XX.js文件。此时这个文件是将react,jquery等代码的代码都组装到里面了,具体没研究。后续肯定要分离开,不然没法复用公共库了。

 

# 5如何在webpack中使用jquery

    最简单的方法就是在html中将jquery的文件引入进来,然后直接调用即可。本文这里所想实现的(或者说学习的)是将jquery进入到工程模块,一并打包。

    这个时候就需要首先安装jquery

     npm install --save  jquery   

    #这里其实用--save-dev也可以,因为只要improt了并使用了的函数或者库,不管他是devDependencies或者dependencies里都会进行打包处理。具体参看:https://zhuanlan.zhihu.com/p/215887185

    #这种与nodejs做后端用的express框架那种不一样。

 

    然后在js代码中引入jquery

import $ from 'jquery';
//或者使用 var $ = require("jquery");
 
  $.ajax({
    url: gf.DOMAIN+'api/getuserinfo',
    type: 'GET',
        xhrFields: {withCredentials: true},
        cache:false,
    data: {},
。。。。。

  

  这是时候用npm run build会发现最终的js包变大了很多,就是把jquery代码也写进去了。当然也可以将公共库分离出来避免多个页面的js多次重复打包

 

#在webpack5中使用css  sass  scss

     npm install --save-dev style-loader css-loader sass-loader sass  #笔者版本为css-loader@6.7.3  sass-loader@13.2.2   style-loader@3.3.2  sass@1.62.0

        css-loader: 把 css 文件编译为 CommonJS 模块,并将该模块引入到 JS 中。

        style-loader:创建 <style>标签,将 JS 中的 CSS 添加到 HTML中。

        sass-loader、sass:不解释。

   webpack.config.js中rules中增加如下:

module: {
    rules: [
      ...
      {
        test: /\.s?[ca]ss$/, //sass 或者scss  css
        use: [//加载顺序是从后先做,即先sass-loader,再css-loader,最后style-loader。
          'style-loader',//style-loader是将css放置到页面上 
          'css-loader',
          'sass-loader',
        ]
      }
    ]
  },

  新建一个app.scss文件

.app-frame {
    margin: auto;
    width: 100%;
    max-width: 1000px;
  }

  app.js中引入文件

import './app.scss'
。。。
。。。

    render () {
        return(
            <div className='app-frame'></div>
        );
    }
}
ReactDOM.render(
    <Index />,
    document.getElementById('content')

  npm run build后,刷新页面直接生效

 

#在webpack5中使用BootStrap

     参考https://getbootstrap.com/docs/4.0/getting-started/webpack/

    npm install --save bootstrap@4.6.2  jquery popper.js   #注意popper后面必须有.js,原因不知。popper的版本为1.16.1。

     #使用bootstrap必须安装popper.js和jquery。不过笔者经过实验,对于bootstrap4.6.2版本,其安装的时候,会将popper.js和jquery默认进行安装。所以其实只需要install --save bootstrap@4.6.2即可

    根据 https://v4.bootcss.com/docs/getting-started/introduction/  可知,一般bootstrap有2中调用依赖关系,本节使用的是第二种,即插件独立:

    <!-- Bootstrap 的 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">

。。。
    <!-- JavaScript 文件是可选的。从以下两种建议中选择一个即可! -->

    <!-- 选项 1:jQuery 和 Bootstrap 集成包(集成了 Popper) -->
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>

    <!-- 选项 2:Popper 和 Bootstrap 的 JS 插件各自独立 -->
    <!--
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.min.js" integrity="sha384-+sLIOodYLS7CIrQpBjl+C7nPvqq+FbNUBDunl/OZv93DB7Ln/533i8e/mZXLi/P+" crossorigin="anonymous"></script>
    -->
  </body>

  js代码中引入bootstrap,根据文档(和实际实验)popper.js和jquery不需要手动引入

//import 'popper.js'
//import 'jquery' import 'bootstrap'

  

     app.scss中直接引入bootstrap的s?[ca]ss文件如下:(当然在app.js中直接import也行)

//app.scss
。。。。$lightGrayColor:#eee;
@import '~bootstrap/scss/bootstrap';
.app-frame {
    ma。。。。

  

 

 

#devtool的配置

   Webpack里有个配置项叫做devtool,这个配置项主要是用于配置打包后的代码映射,方便我们在debug的时候查看到源代码的位置,主要是发生异常错误的时候,可以定位到准确位置。

 

    output: {
		XXX
	},
	module: {
		rules: [
			{
			}
		]
	},
	devtool: 'inline-source-map',//如果是生产环境,用'source-map'
	plugins:[
	XXX

  在生产环境,一般使用'source-map',此时js的包会比没有devtool的时候大一些,而且多了要给*.map文件。浏览器就是通过这个map定位到错误。如果是在生产环境使用'inline-source-map',操作上也可以,但是那么js文件会很大,所以极其不推荐。

       在开发环境,按照官方推荐,一般使用'inline-source-map'。虽然有source-map,但是也有inline字段,所以这个时候,也是生产一个map文件内容对应的base64插入到*.js里面去。操作上,也可以使用'source-map',只是一边使用'inline-source-map'。

 

 
 

#文件引入file-loader(图片,附件等)

   file-loader可以协助在webpack中引入图片等。

   npm install --save-dev file-loader //@6.2.0

   在配置文件中

	module: {
		rules: [
			{
				test: /\.js|jsx$/,
                XXX
			},
			{
				test: /\.(png|svg|jpg|ico|gif|bmp|pdf|jpe?g)$/,
				use: [
					{
						loader:'file-loader',
						options:{
							name:'[name].[ext]',
							outputPath:'img'//会输出到dist下的img文件夹
						}
					}
				]
			},
		]
	},
	plugins:[

  

 js文件中的代码这样写:

import logo from './img/cil-notes.svg';
<img height='100%' src={logo} />

  

   注:与file-loader对应常用的loader是已下3个,本文只涉及到file-loader:

     raw-loader 将文件导入为字符串

     url-loader 将文件作为 data URI 内联到 bundle 中

     file-loader 将文件发送到输出目录

  然而在webpack5开始,不建议使用以上3个了,而改用以下的形式【https://www.webpackjs.com/guides/asset-modules/#root】:

资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:

  • asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。
  • asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。
  • asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
  • asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现。

当在 webpack 5 中使用旧的 assets loader(如 file-loader/url-loader/raw-loader 等)和 asset 模块时,你可能想停止当前 asset 模块的处理,并再次启动处理,这可能会导致 asset 重复,你可以通过将 asset 模块的类型设置为 'javascript/auto' 来解决。

    具体用法参考下一篇文章:webpack 学习笔记2(进阶)

 

 

XXX

   XX

 

posted @ 2023-04-06 22:09  东方春  阅读(74)  评论(0)    收藏  举报