[原]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\'
        })
    ]
};
View Code

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]);
View Code

4.  /http/services/index.js 文件

\'use strict\';
var angular = require(\'angular\');

var servicesModule = angular.module(\'wabgApp.services\', []);

exports = module.exports = {
    default: servicesModule.name
};
View Code

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
};
View Code

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;
View Code

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
};
View Code

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;
View Code

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;
View Code

10.  /http/views/demo/demo.view.html 文件

<div style="color:blue">This is a demo directive.</div>
<br/>
View Code

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>
View Code

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\'
        })
    ]
};
View Code

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]);
View Code

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
};
View Code

6. 创建 /http/directives/menu/menu.directive.js 文件

\'use strict\';

function menuDirective(views) {
    return {
        restrict: \'E\',
        templateUrl: views.menu
    };
}

exports = module.exports = menuDirective;
View Code

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;
View Code

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>
View Code

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>
View Code

10 创建 /http/scss/index.scss 文件

@import "~bootstrap/scss/bootstrap";
View Code

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\'
        })
    ]
};
View Code

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实战

angularjs1.3验证

angularjs1-3,$apply,$watch

如何Angularjs1.3在页面中输出带Html标记的文本

Angular2 & angularjs1