Giter Site home page Giter Site logo

webpack's Introduction

👨‍🚒 About me

🔥 Project

  • 🔰 Compile Hero Visual Studio Code Extension For Compiling Language.
  • 🎹 Piano Play piano with 8 keys on the keyboard is given to yourself.

webpack's People

Contributors

wscats avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

webpack's Issues

webpack如何全局加载第三方插件jQuery

1. 直接引入难以引入插件

// 可以直接引入jquery,但没有全局的jQuery变量
import $ from 'jquery'
// 如果此时直接引入jquery 插件,则失败,如
import 'jquery-ui' // 错误,将会找不到jquery-ui注册的相关方法

2. ProvidePlugin难以引入插件

在webpack.config.js中添加插件ProvidePlugin

plugins: [
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery"
    }),
  ]
//  $函数会自动添加到当前模块的上下文,无需显示声明

这里注意不要在头部忘了添加

var webpack = require('webpack');

问题是依旧没有全局的$函数,所以导入插件依旧会失败,并且如果有eslint这样的preLoads,调用语句也难以通过语法校验(因为没有声明$就直接使用),仅这一点,对于我这样的代码处女座就难以接受。

3. expose-loader推荐使用

不需要任何其他的插件配合,只要将下面的代码添加到所有的loader之前

 {
    test: require.resolve('jquery'),
    loader: 'expose?jQuery!expose?$'
 }

引用时改为如下方式

import $ from 'expose?$!jquery'
import 'jquery-ui' //插件可用   

imports-loader、script-loader同样可达到此效果,配置与功能都非常相似,在此不一一说明。

4. 包装jquery推荐使用

此方法只依赖于自己,完全不需要任何其他插件与加载器,创建jquery的包装对象jquery-vendor.js

import $ from 'jquery'
window.$ = $
window.jQuery = $
export default $
//以后引用jquery时指向jquery-vendor.js
import $ from '../assets/jquery-vendor.js'
import 'jquery-ui'
//  此时UI的方法全部可用,如果需要引用bootstrap,可参照此方法
//  window.jQuery = window.$ = require('jquery')

为了调用方便,可在webpack配置文件中创建jquery-vendor.js的别名

alias: {
    jquery: 'src/assets/jquery-vendor.js' // 将其指向jquery-vendor.js所在位置
}   
resolve: {
    alias: {
        jquery: "jquery/src/jquery" // 全局配置jquery
    }
}

5.其他参考

webpack如何全局加载第三方插件,类似jQuery?

webpack中babel-loader转译ES2015

babel-loader转译ES2015
webpack通过Babel运行我们的资源文件,我们就可以使用ES2015的特性

  • 1.安装Babel和presets:
npm install babel-core babel-preset-es2015
  • 2.安装babel-loader:
npm install babel-loader --save-dev
  • 3.添加一个以.babelrc命名的文件,并使用presets配置Babel//这点很重要,这个配置是必须的
{ "presets": [ "es2015" ] }
  • 4.修改 webpack.config.js使得'babel-loader'来处理所有.js结尾的文件
module.exports = {
	devtool: 'eval-source-map', //用于调试代码
	entry: __dirname + "/main.js", //入口文件
	output: {
		path: __dirname + "/public", //打包后的文件存放的地方
		filename: "bundle.js" //打包后输出文件的文件名
	},
	module: {
		loaders: [{
			test: /\.css$/,
			loader: 'style-loader!css-loader'
		}, {
			test: /\.(png|jpg)$/,
			loader: 'url-loader?limit=8192'
		}, {
			test: /\.js$/,
			exclude: /node_modules/,//配置是将node_modules文件下的内容排除在外,降低编译时间。
			loader: "babel-loader",
		}, {
			test: /\.vue$/,
			loader: 'vue-loader'
		}]
	},
	//ES6转ES5 webpack2中不支持这个属性的写法了,检测不出babel属性值并报错,用.babelrc代替此处
	//执行webpack记得注释一下
	//	babel: {
	//		presets: ['es2015']
	//	},
	devServer: {
		contentBase: "./public", //本地服务器所加载的页面所在的目录
		historyApiFallback: true, //不跳转
		inline: true //实时刷新
	},
	resolve: {
		alias: {
			vue: 'vue/dist/vue.js'
		}
	}
}

其中exclude: /node_modules/配置是将node_modules文件下的内容排除在外,降低编译时间

webpack配置mui

mui官网下载mui

目录结构

image

main.js

然后可以把mui保存在全局的window对象里面,就像jQuery的配置一样

require("./mui/css/mui.css")
window.mui = require("./mui/js/mui.js")

然后你就可以写一个mui样式的组件,例如下面的例子

<template>
    <div>
        <!--下拉刷新容器-->
        <div id="refreshContainer" class="mui-content mui-scroll-wrapper">
            <div class="mui-scroll">
                <!--数据列表-->
                <ul class="mui-table-view mui-table-view-chevron">

                </ul>
            </div>
        </div>
    </div>
</template>
<script>
    export default {
        replace: false,
        data() {
            return {}
        },
        methods: {},
        components: {},
        mounted() {
            mui.init({
                pullRefresh: {
                    container: "#refreshContainer", //下拉刷新容器标识,querySelector能定位的css选择器均可,比如:id、.class等
                    down: {
                        height: 50, //可选,默认50.触发下拉刷新拖动距离,
                        auto: true, //可选,默认false.自动下拉刷新一次
                        contentdown: "下拉可以刷新", //可选,在下拉可刷新状态时,下拉刷新控件上显示的标题内容
                        contentover: "释放立即刷新", //可选,在释放可刷新状态时,下拉刷新控件上显示的标题内容
                        contentrefresh: "正在刷新...", //可选,正在刷新状态时,下拉刷新控件上显示的标题内容
                        callback: function () {
                            mui('#refreshContainer').pullRefresh().endPulldownToRefresh();
                            console.log("hello")
                        } //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据;
                    }
                }
            });
        },
        directives: {
        }
    }
</script>

在引入mui.css时候,注意要配置ttf格式的加载器(例如file-loader,css-loader和style-loader)

webpack.config.js

{
    test: /\.eot/,
    loader: 'file-loader?prefix=font/'
}, {
    test: /\.woff/,
    loader: 'file-loader?prefix=font/&limit=10000&mimetype=application/font-woff'
}, {
    test: /\.ttf/,
    loader: 'file-loader?prefix=font/'
}, {
    test: /\.svg/,
    loader: 'file-loader?prefix=font/'
}

如果报arguments.callee这个错误,因为ES5在默认严格模式下已经不建议这个用法,所以我们可以给class.extend赋一个带名字的函数,然后Class.extend = Fn,然后注释Class.extend = arguments.callee

Class.extend = function Fn(prop) {
	//code...
	//Class.extend = arguments.callee;
	Class.extend = Fn;
	return Class;
};

简单实现一个webpack的模块化打包工具

webpack打包过程

  1. 读取入口文件内容,一般来说,入口文件需要引入其他封装好的子模块来拓展功能
  2. 通过逐层识别模块依赖。(常见的规范有 CommonJS 、AMD 或者 ES6 的 import 和 export),webpack根据其不同的规范对其进行分析,来获取其他子模块代码的依赖
    1. 先逐级递归识别依赖,构建依赖图谱
    2. 将代码转化成AST抽象语法树
    3. AST阶段中去处理代码
    4. AST抽象语法树变成浏览器可以识别的代码, 然后输出
  3. webpack此时主要任务就是:
    1. 分析代码:AST,分析依赖
    2. 转换代码:比如 omil,vue-loader,预编译语言转化,单文件组件转化
    3. 编译代码:比如 plugin
    4. 输出代码
  4. 最终输出bundle.js也就是需要经过打包后要发布的代码

熟知上面的流程之后,我们可以下载下面四个核心模块,来构建自己的模块工具:

  1. @babel/parser: 通过fs.readFileSync或者fs.readFile读取的本地文件(入口文件)内容,是 buffer 格式,将 读出来的 buffer 内容交给该模块处理,它将返回 AST (抽象语法树)
  2. @babel/traverse: 可以遍历 AST, 可用于ES6代码转化,清除注释,代码格式化,修改代码片段
  3. @babel/core: babel 核心模块,其有个transformFromAst方法,可以将 AST 转化为浏览器可以运行的代码
  4. @babel/preset-env: 将代码转化成 ES5 代码

使用npm或者cnpm下载 babel 模块,下面这几个都是处理 AST 必须要用到的模块:

cnpm install @babel/parser @babel/traverse @babel/core @babel/preset-env --D

编写一个入口文件test1.js来做测试:

console.log(1)
import test from './test.js'
let fn = (a, b) => {
    return a + b
}
const {
    readFileSync
} = require('fs');
const path = require('path');
const {
    parse
} = require('@babel/parser');

const read = fileName => {
    const buffer = readFileSync(fileName, 'utf-8');
    const AST = parse(buffer, { sourceType: 'module' });
    console.log(AST);
};
read(path.resolve('./', 'test1.js'));

让我们分析上面的每一句代码:

  1. 我们引入了内置的fspath模块,一个用于读取本地文件,一个用于处理文件地址
  2. 我们使用了一个同步方法readFileSync读取文件流,注意输出的是二进制buffer,如果要转化为可识别字符串,需要toString()方法,这里我们直接处理buffer格式
  3. buffer数据交给parser.parse()方法处理,转换为下面的AST格式:
Node {
  type: 'File',
  start: 0,
  end: 54,
  loc:
   SourceLocation {
     start: Position { line: 1, column: 0 },
     end: Position { line: 4, column: 1 } },
  program:
   Node {
     type: 'Program',
     start: 0,
     end: 54,
     loc: SourceLocation { start: [Position], end: [Position] },
     sourceType: 'module',
     interpreter: null,
     body: [ [Node], [Node] ],
     directives: [] },
  comments: [] }

经过我们上面的转化,我们已经得到入口文件的 AST,我们需要用一个装饰器ImportDeclaration把所有的import片段给筛选出来,并获取他们的路径,所以我们需要在read函数中补充以下代码,拓展其收集依赖的功能:

const read = fileName => {
    const buffer = readFileSync(fileName, 'utf-8');
    const AST = parse(buffer, { sourceType: 'module' });
    // 依赖收集
    const dependencies = {};
    // 使用 traverse 来遍历 AST
    traverse(AST, {
        // 函数名是 AST 中包含的内容,参数是一些节点,node 表示这些节点下的子内容
        ImportDeclaration({ node }) {
            // 我们从抽象语法树里面拿到的路径是相对路径,然后我们要处理它,在 bundle.js 中才能正确使用
            const dirname = path.dirname(fileName); 
            // 将 dirname 和获取到的依赖联合生成绝对路径
            const newDirname = './' + path.join(dirname, node.source.value).replace('\\', '/');
            // 将源路径和新路径以键对值(key-value)的形式存储起来
            dependencies[node.source.value] = newDirname; 
        }
    })

    // 将抽象语法树转换成浏览器可以运行的代码
    const { code } = babel.transformFromAst(AST, null, {
        presets: ['@babel/preset-env']
    })

    return {
        fileName,
        dependencies,
        code
    }
};

再次执行read()函数,我们会得到以下对象:

{
    fileName: '/Users/eno/Documents/Wscats/1000phone/1905-1/mini-webpack/test/test1.js',
    dependencies: {
        './test.js': './/Users/eno/Documents/Wscats/1000phone/1905-1/mini-webpack/test/test.js'
    },
    code: '"use strict";\n\nvar _test = _interopRequireDefault(require("./test.js"));\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }\n\nconsole.log(1);\n\nvar fn = function fn(a, b) {\n  return a + b;\n};'
}

webpack+angular

文件目录

image

webpack+angular demo

安装webpack及其他组件

npm install webpack -g
npm install angular
//还要安装一系列加载器(loader):
npm install style-loader css-loader url-loader raw-loader

配置文件webpack.config.js

//npm install style-loader css-loader url-loader raw-loader
module.exports = {
	devtool: 'eval-source-map', //用于调试代码
	entry: __dirname + "/app.js", //入口文件
	output: {
		path: __dirname + "/public", //打包后的文件存放的地方
		filename: "bundle.js" //打包后输出文件的文件名
	},
	module: {
		loaders: [{
			test: /\.html$/,
			loader: 'raw-loader'
		}, {
			test: /\.css$/,
			loader: 'style-loader!css-loader'
		}, {
			test: /\.(png|jpg)$/,
			loader: 'url-loader?limit=8192'
		}]
	},
}

入口主文件app.js

angular = require('angular');
var app = angular.module('myApp', []);
require('./controller/index.js')(app);
require('./directive/xheader/xheader.js')(app);
require('./service/tool.js')(app);

入口页面index.html

<!DOCTYPE html>
<html ng-app="myApp">
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<div ng-controller="indexCtrl">
			<p>{{name}}</p>
			<xheader></xheader>
		</div>
	</body>
	<script src="bundle.js"></script>
</html>

指令文件xheader.js

module.exports = function(app) {
	require('./xheader.css');
	app.directive('xheader', [function() {
		return {
			template: require('./xheader.html')
			//templateUrl: './xheader.html'
		}
	}])
}

xheader.css

header {
	color: red;
}

服务文件service.js

module.exports = function(app) {
	app.service('tool', [function() {
		return {
			sum: function(a, b) {
				return a + b;
			}
		}
	}])
}

webpack加载css文件中的eot,ttf等格式文件

需要先安装file-loader

cnpm install file-loader

然后配置加载器

{
    test: /\.eot/,
    loader: 'file-loader?prefix=font/'
}, {
    test: /\.woff/,
    loader: 'file-loader?prefix=font/&limit=10000&mimetype=application/font-woff'
}, {
    test: /\.ttf/,
    loader: 'file-loader?prefix=font/'
}, {
    test: /\.svg/,
    loader: 'file-loader?prefix=font/'
}

webpack如何全局加载第三方插件,类似jQuery?

1. 直接引入难以引入插件

// 可以直接引入jquery,但没有全局的jQuery变量
import $ from 'jquery'
// 如果此时直接引入jquery 插件,则失败,如
import 'jquery-ui' // 错误,将会找不到jquery-ui注册的相关方法

2. ProvidePlugin难以引入插件

在webpack.config.js中添加插件ProvidePlugin

plugins: [
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery"
    }),
  ]
//  $函数会自动添加到当前模块的上下文,无需显示声明

这里注意不要在头部忘了添加

var webpack = require('webpack');

问题是依旧没有全局的$函数,所以导入插件依旧会失败,并且如果有eslint这样的preLoads,调用语句也难以通过语法校验(因为没有声明$就直接使用),仅这一点,对于我这样的代码处女座就难以接受。

3. expose-loader推荐使用

不需要任何其他的插件配合,只要将下面的代码添加到所有的loader之前

 {
    test: require.resolve('jquery'),
    loader: 'expose?jQuery!expose?$'
 }

引用时改为如下方式

import $ from 'expose?$!jquery'
import 'jquery-ui' //插件可用   

imports-loader、script-loader同样可达到此效果,配置与功能都非常相似,在此不一一说明。

4. 包装jquery推荐使用

此方法只依赖于自己,完全不需要任何其他插件与加载器,创建jquery的包装对象jquery-vendor.js

import $ from 'jquery'
window.$ = $
window.jQuery = $
export default $
//以后引用jquery时指向jquery-vendor.js
import $ from '../assets/jquery-vendor.js'
import 'jquery-ui'
//  此时UI的方法全部可用,如果需要引用bootstrap,可参照此方法
//  window.jQuery = window.$ = require('jquery')

为了调用方便,可在webpack配置文件中创建jquery-vendor.js的别名

alias: {
    jquery        : 'src/assets/jquery-vendor.js' //    将其指向jquery-vendor.js所在位置
}   
       resolve: {
		alias: {
			jquery: "jquery/src/jquery"//全局配置jquery
		}
	}

5.其他参考

webpack如何全局加载第三方插件,类似jQuery?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.