[原]Webpack 3 + AngularJS1.* + Bootstrap 4 + Mapbox-gl
Posted Warmth & Chilliness
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[原]Webpack 3 + AngularJS1.* + Bootstrap 4 + Mapbox-gl相关的知识,希望对你有一定的参考价值。
直接上步骤
一、创建项目
1. 使用VSCode建立项目目录结构如下:
文档结构
wabg
├── http
│ ├── app.js
│ ├── controllers
│ │ └── index.js
│ ├── directives
│ │ └── index.js
│ ├── services
│ │ └── index.js
│ ├── templates
│ │ └── index.tmpl.html
│ └── views
│ └── index.js
├── package.json
└── webpack.config.js
二、配置webpack和angularjs
1. 安装webpack和angularjs所需的依赖项
npm install webpack webpack-dev-server angular angular-ui-router jquery html-webpack-plugin ngtemplate-loader html-loader --save-dev
2. 创建一个简单的页面,通过这个非常简单的页面,验证webpack和angular各要素是否能够正常使用,该页面要素包括:
红色部分是点击“getAuthor”按钮后由AngularJS的Controller赋值而出现的;
蓝色部分是通过一个directive渲染的
绿色部分是通过jQuery动态添加的
文档结构如下:
wabg
├── dist
│ ├── index.html
│ └── js
│ ├── angular.bundle.js
│ ├── angular.bundle.js.map
│ ├── app.bundle.js
│ ├── app.bundle.js.map
│ ├── vendor.bundle.js
│ └── vendor.bundle.js.map
├── http
│ ├── app.js
│ ├── controllers
│ │ ├── home
│ │ │ └── home.controller.js
│ │ └── index.js
│ ├── directives
│ │ ├── demo
│ │ │ └── demo.directive.js
│ │ └── index.js
│ ├── services
│ │ └── index.js
│ ├── templates
│ │ └── index.tmpl.html
│ └── views
│ ├── demo
│ │ └── demo.view.html
│ └── index.js
├── package.json
└── webpack.config.js
下面为本页面用到的所有代码
2. /webpack.config.js 文件
\'use strict\'; var path = require(\'path\'); var webpack = require(\'webpack\'); var HtmlWebpackPlugin = require(\'html-webpack-plugin\'); module.exports = { devtool: \'evel-source-map\', context: path.resolve(__dirname + \'/http\'), entry: { app: \'./app.js\', vendor: [\'jquery\'], angular: [\'angular\', \'angular-ui-router\'] }, output: { path: path.resolve(__dirname + \'/dist\'), filename: \'js/[name].bundle.js\', publicPath: \'\', }, devServer: { historyApiFallback: true, inline: true }, module: { rules: [ { test: /\\.view.html$/, use: [ { loader: \'ngtemplate-loader\' }, { loader: \'html-loader\' } ], } ] }, plugins: [ new HtmlWebpackPlugin({ template: __dirname + \'/http/templates/index.tmpl.html\', chunksSortMode: function (chunk1, chunk2) { var order = [\'angular\', \'vendor\', \'app\']; var order1 = order.indexOf(chunk1.names[0]); var order2 = order.indexOf(chunk2.names[0]); return order1 - order2; } }), new webpack.optimize.CommonsChunkPlugin({ names: [\'vendor\', \'angular\'], filename: \'js/[name].bundle.js\' }), new webpack.ProvidePlugin({ $: \'jquery\', jQuery: \'jquery\', \'window.jQuery\': \'jquery\' }) ] };
3. /http/app.js 文件
\'use strict\'; var angular = require(\'angular\'); var uirouter = require(\'angular-ui-router\'); var services = require(\'./services\'); var views = require(\'./views\'); var directives = require(\'./directives\'); var controllers = require(\'./controllers\'); angular.module(\'wabgApp\', [uirouter.default, services.default, views.default, directives.default, controllers.default]);
4. /http/services/index.js 文件
\'use strict\'; var angular = require(\'angular\'); var servicesModule = angular.module(\'wabgApp.services\', []); exports = module.exports = { default: servicesModule.name };
5. /http/controllers/index.js 文件
\'use strict\'; var angular = require(\'angular\'); var homeController = require(\'./home/home.controller\'); var controllersModule = angular.module(\'wabgApp.controllers\', []) .controller(homeController.name, [\'$scope\', homeController]); exports = module.exports = { default: controllersModule.name, homeController: homeController.name };
6. /http/controllers/home/home.controller.js 文件
\'use strict\'; function homeController($scope) { $scope.name = \'think8848\'; $scope.getAuthor = function (name) { $scope.author = name; }; } exports = module.exports = homeController;
7. /http/directives/index.js 文件
\'use strict\'; var angular = require(\'angular\'); var demoDirective = require(\'./demo/demo.directive\'); var directivesModule = angular.module(\'wabgApp.directives\', []) .directive(demoDirective.name, [\'views\', demoDirective]); exports = module.exports = { default: directivesModule.name, demoDirective: demoDirective.name };
8. /http/directives/demo/demo.directive.js 文件
\'use strict\'; function demoDirective(views) { return { restrict: \'E\', templateUrl: views.demo, link: function (scope, elem) { $(elem).after(\'<div style="color: green">The content generated by jQuery</div>\'); } }; } exports = module.exports = demoDirective;
9. /http/views/index.js 文件
\'use strict\'; var angular = require(\'angular\'); function views() { return { demo: require(\'./demo/demo.view.html\') }; } exports = module.exports = views(); var viewsModule = angular.module(\'wabgApp.views\', []) .constant(views.name, exports); exports.default = viewsModule.name;
10. /http/views/demo/demo.view.html 文件
<div style="color:blue">This is a demo directive.</div> <br/>
11. /http/templates/index.tmpl.html 文件
<!DOCTYPE html> <html ng-app="wabgApp"> <head> <meta charset="UTF-8"> <title>Webpack App</title> <style> .ng-cloak { display: none; } </style> </head> <body> <div id="root" ng-controller="homeController"> The Author is: <lable ng-ng-cloak class="ng-cloak" style="color:red">{{author}}</lable><br/> <input type="button" ng-click="getAuthor(name)" value="getAuthor" /> <br/> <br/> <demo-directive></demo-directive> </div> </body> </html>
12. 修改 package.json 文件中的 scripts 节点如下:
"scripts": { "test": "echo \\"Error: no test specified\\" && exit 1", "start": "webpack", "server": "webpack-dev-server --open" },
13. 运行 npm run server 命令
运行界面效果
三、加入Bootstrap 4.0支持
1. 当前Bootstrap的最新版本是v4.0 Beta,在使用webpack时有两点需要注意:一是默认的样式文件为 scss 样式;二是当前v4.0 Beta版中默认不提供图标了。首先依然是安装依赖项
npm install bootstrap@4.0.0-beta expose-loader style-loader css-loader postcss-loader precss autoprefixer sass-loader url-loader file-loader popper.js exports-loader node-sass --save-dev
2. 为Bootstrap加入图标支持,图标使用FontAwesome(官网)
2.1 先下载Bootstrap 4.0.0 beta版(本人虽不是前端,但是对前端框架和库的版本也无力吐槽了)的源代码,友情提示:经测试 npm 上下载的发布包是无法顺利集成图标的
git clone https://github.com/twbs/bootstrap.git
2.2 下载FontAwesome字体包(本文下载到的版本是v4.7.0)
2.3 将下载好的FontAwesome解压后,相关的子目录放到指定位置
font-awesome 和 scss 放到 bootstrap 源代码根目录下, fonts 放到 bootstrap 源代码的 dist 目录下
2.4 使用VSCode打开 bootstrap 源代码根目录,修改 /scss/bootstrap.scss 文件,在最下面添加两行代码,注意:一定要在文件最后保留一行空行
$fa-font-path: "../fonts"; @import "../font-awesome/scss/font-awesome.scss";
2.5 使用 npm install 下载依赖项,然后再使用 npm run dist 命令发布
在发布的过程中,跳出来很多绿的,蓝的说明没问题,过会儿就好了
2.6 使用源代码包中的内容替换 wabg 项目中 node_modules/bootstrap 中的相应文件夹
2.7 编辑 /wabg/node_modules/bootstrap/scss/bootstrap.scss 文件,将之前代码上级目录的 ../ 替换为 ~bootstrap/ ,在 fonts 目录前面加上 dist 目录
至此,Bootstrap的准备工作完成,下面开始添加演示代码,项目文档结构如下:
wabg ├── dist │ ├── index.html │ └── js │ ├── angular.bundle.js │ ├── angular.bundle.js.map │ ├── app.bundle.js │ ├── app.bundle.js.map │ ├── vendor.bundle.js │ └── vendor.bundle.js.map ├── http │ ├── app.js │ ├── controllers │ │ ├── home │ │ │ └── home.controller.js │ │ └── index.js │ ├── directives │ │ ├── demo │ │ │ └── demo.directive.js │ │ ├── index.js │ │ └── menu │ │ └── menu.directive.js │ ├── scss │ │ └── index.scss │ ├── services │ │ └── index.js │ ├── templates │ │ └── index.tmpl.html │ └── views │ ├── demo │ │ └── demo.view.html │ ├── index.js │ └── menu │ └── menu.view.html ├── package.json └── webpack.config.js
3. 编辑 webpack.config.js 文件
\'use strict\'; var path = require(\'path\'); var webpack = require(\'webpack\'); var HtmlWebpackPlugin = require(\'html-webpack-plugin\'); module.exports = { devtool: \'evel-source-map\', context: path.resolve(__dirname + \'/http\'), entry: { app: \'./app.js\', vendor: [\'jquery\', \'popper.js\', \'bootstrap\', \'bootstrap/js/dist/util.js\', \'bootstrap/js/dist/dropdown.js\'], angular: [\'angular\', \'angular-ui-router\'] }, output: { path: path.resolve(__dirname + \'/dist\'), filename: \'js/[name].bundle.js\', publicPath: \'\', }, devServer: { historyApiFallback: true, inline: true }, module: { rules: [ { test: /\\.view.html$/, use: [ { loader: \'ngtemplate-loader\' }, { loader: \'html-loader\' } ], }, { test: /\\.css$/, use: [{ loader: \'style-loader\' }, { loader: \'css-loader\' }] }, { test: /\\.(scss)$/, use: [{ loader: \'style-loader\', }, { loader: \'css-loader\', }, { loader: \'postcss-loader\', options: { plugins: function () { return [ require(\'precss\'), require(\'autoprefixer\') ]; } } }, { loader: \'sass-loader\' }] }, { test: /\\.(jpg|png|gif)(\\?.*$|$)/, use: [ { loader: \'url-loader\', options: { limit: 10000, name: \'./images/[name].[ext]\' } } ] }, { test: /\\.(woff|woff2|eot|ttf|svg)(\\?.*$|$)/, use: [{ loader: \'file-loader\', options: { name: \'./fonts/[name].[ext]\' } }] } ] }, plugins: [ new HtmlWebpackPlugin({ template: __dirname + \'/http/templates/index.tmpl.html\', chunksSortMode: function (chunk1, chunk2) { var order = [\'angular\', \'vendor\', \'app\']; var order1 = order.indexOf(chunk1.names[0]); var order2 = order.indexOf(chunk2.names[0]); return order1 - order2; } }), new webpack.optimize.CommonsChunkPlugin({ names: [\'vendor\', \'angular\'], filename: \'js/[name].bundle.js\' }), new webpack.ProvidePlugin({ $: \'jquery\', jQuery: \'jquery\', \'window.jQuery\': \'jquery\', Popper: [\'popper.js\', \'default\'], Util: \'exports-loader?Util!bootstrap/js/dist/util\', Dropdown: \'exports-loader?Dropdown!bootstrap/js/dist/dropdown\' }) ] };
4. 修改 /http/app.js 文件
\'use strict\'; var angular = require(\'angular\'); var uirouter = require(\'angular-ui-router\'); var scss = require(\'./scss/index.scss\'); var services = require(\'./services\'); var directives = require(\'./directives\'); var controllers = require(\'./controllers\'); var views = require(\'./views\'); angular.module(\'wabgApp\', [uirouter.default, services.default, views.default, directives.default, controllers.default]);
5. 编辑 /http/directives/index.js 文件
\'use strict\'; var angular = require(\'angular\'); var demoDirective = require(\'./demo/demo.directive\'); var menuDirective = require(\'./menu/menu.directive\'); var directivesModule = angular.module(\'wabgApp.directives\', []) .directive(demoDirective.name, [\'views\', demoDirective]) .directive(menuDirective.name, [\'views\', menuDirective]); exports = module.exports = { default: directivesModule.name, demoDirective: demoDirective.name, menuDirective: menuDirective };
6. 创建 /http/directives/menu/menu.directive.js 文件
\'use strict\'; function menuDirective(views) { return { restrict: \'E\', templateUrl: views.menu }; } exports = module.exports = menuDirective;
7. 编辑 /http/views/index.js 文件
\'use strict\'; var angular = require(\'angular\'); function views() { return { demo: require(\'./demo/demo.view.html\'), menu: require(\'./menu/menu.view.html\') }; } exports = module.exports = views(); var viewsModule = angular.module(\'wabgApp.views\', []) .constant(views.name, exports); exports.default = viewsModule.name;
8. 创建 /http/views/menu/menu.view.html 文件
<nav class="navbar navbar-light bg-light"> <a class="navbar-brand" href="#"> <span width="30" height="30" class="d-inline-block align-top fa fa-camera-retro fa-5x" /> Bootstrap </a> </nav>
9. 修改 /http/templates/index.tmpl.html 文件
<!DOCTYPE html> <html ng-app="wabgApp"> <head> <meta charset="UTF-8"> <title>Webpack App</title> <style> .ng-cloak { display: none; } </style> </head> <body> <div id="root" ng-controller="homeController"> <menu-directive></menu-directive> The Author is: <lable ng-ng-cloak class="ng-cloak" style="color:red">{{author}}</lable><br/> <input type="button" ng-click="getAuthor(name)" value="getAuthor" /> <br/> <br/> <demo-directive></demo-directive> </div> </body> </html>
10 创建 /http/scss/index.scss 文件
@import "~bootstrap/scss/bootstrap";
11. 运行 npm run server 就能看到效果了
四、加入Mapbox-gl支持
1. 安装依赖项
npm install mapbox-gl angular-mapboxgl-directive --save-dev
2. 下面演示的是AngularJS中使用MapBox-gl-js,为了显示效果,加入了一个很简单的About页面,用于演示地图和普通VIew的切换。如下图所示:
项目目录结构如下
wabg ├── dist │ ├── fonts │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── index.html │ └── js │ ├── angular.bundle.js │ ├── angular.bundle.js.map │ ├── app.bundle.js │ ├── app.bundle.js.map │ ├── vendor.bundle.js │ └── vendor.bundle.js.map ├── http │ ├── app.js │ ├── controllers │ │ ├── about │ │ │ └── about.controller.js │ │ ├── home │ │ │ └── home.controller.js │ │ ├── index.js │ │ └── map │ │ └── map.controller.js │ ├── css │ │ └── index.css │ ├── directives │ │ ├── demo │ │ │ └── demo.directive.js │ │ ├── index.js │ │ └── menu │ │ └── menu.directive.js │ ├── scss │ │ └── index.scss │ ├── services │ │ ├── index.js │ │ └── map-styles │ │ └── default-style.js │ ├── templates │ │ └── index.tmpl.html │ └── views │ ├── about │ │ └── about.view.html │ ├── demo │ │ └── demo.view.html │ ├── index.js │ ├── map │ │ └── map.view.html │ └── menu │ └── menu.view.html ├── package.json └── webpack.config.js
3. 修改 webpack.config.js 文件
\'use strict\'; var path = require(\'path\'); var webpack = require(\'webpack\'); var HtmlWebpackPlugin = require(\'html-webpack-plugin\'); module.exports = { devtool: \'evel-source-map\', context: path.resolve(__dirname + \'/http\'), entry: { app: \'./app.js\', vendor: [\'jquery\', \'popper.js\', \'bootstrap\', \'bootstrap/js/dist/util.js\', \'bootstrap/js/dist/dropdown.js\', \'mapbox-gl\', \'angular-mapboxgl-directive\'], angular: [\'angular\', \'angular-ui-router\'] }, output: { path: path.resolve(__dirname + \'/dist\'), filename: \'js/[name].bundle.js\', publicPath: \'\', }, devServer: { historyApiFallback: true, inline: true }, module: { rules: [ { test: /\\.view.html$/, use: [ { loader: \'ngtemplate-loader\' }, { loader: \'html-loader\' } ], }, { test: /\\.css$/, use: [{ loader: \'style-loader\' }, { loader: \'css-loader\' }] }, { test: /\\.(scss)$/, use: [{ loader: \'style-loader\', }, { loader: \'css-loader\', }, { loader: \'postcss-loader\', options: { plugins: function () { return [ require(\'precss\'), require(\'autoprefixer\') ]; } } }, { loader: \'sass-loader\' }] }, { test: /\\.(jpg|png|gif)(\\?.*$|$)/, use: [ { loader: \'url-loader\', options: { limit: 10000, name: \'./images/[name].[ext]\' } } ] }, { test: /\\.(woff|woff2|eot|ttf|svg)(\\?.*$|$)/, use: [{ loader: \'file-loader\', options: { name: \'./fonts/[name].[ext]\' } }] } ] }, plugins: [ new HtmlWebpackPlugin({ template: __dirname + \'/http/templates/index.tmpl.html\', chunksSortMode: function (chunk1, chunk2) { var order = [\'angular\', \'vendor\', \'app\']; var order1 = order.indexOf(chunk1.names[0]); var order2 = order.indexOf(chunk2.names[0]); return order1 - order2; } }), new webpack.optimize.CommonsChunkPlugin({ names: [\'vendor\', \'angular\'], filename: \'js/[name].bundle.js\' }), new webpack.ProvidePlugin({ $: \'jquery\', jQuery: \'jquery\', \'window.jQuery\': \'jquery\', Popper: [\'popper.js\', \'default\'], Util: \'exports-loader?Util!bootstrap/js/dist/util\', Dropdown: \'exports-loader?Dropdown!bootstrap/js/dist/dropdown\', mapboxgl: \'mapbox-gl\' }) ] };
4. 修改 /http/app.js 文件
\'use strict\'; var angular = require(\'angular\'); var uirouter = require(\'angular-ui-router\'); var css = require(\'./css/index.css\'); var scss = require(\'./scss/index.scss\'); var services = require(\'./services\'); var directives = require(\'./directives\'); var controllers = require(\'./controllers\'); var views = require(\'./views\'); var mapboxglDirective = \'mapboxgl-directive\'; angular.module(\'wabgApp\', [uirouter.default, services.default, views.以上是关于[原]Webpack 3 + AngularJS1.* + Bootstrap 4 + Mapbox-gl的主要内容,如果未能解决你的问题,请参考以下文章electron-vue架构解析3-开发环境启动流程分析(原)
第1208期AngularJS 1.x平滑升级Angular实战